freeablo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
nuklear.h
Go to the documentation of this file.
1 /*
2  Nuklear - 1.37.0 - public domain
3  no warrenty implied; use at your own risk.
4  authored from 2015-2017 by Micha Mettke
5 
6 ABOUT:
7  This is a minimal state graphical user interface single header toolkit
8  written in ANSI C and licensed under public domain.
9  It was designed as a simple embeddable user interface for application and does
10  not have any dependencies, a default renderbackend or OS window and input handling
11  but instead provides a very modular library approach by using simple input state
12  for input and draw commands describing primitive shapes as output.
13  So instead of providing a layered library that tries to abstract over a number
14  of platform and render backends it only focuses on the actual UI.
15 
16 VALUES:
17  - Graphical user interface toolkit
18  - Single header library
19  - Written in C89 (a.k.a. ANSI C or ISO C90)
20  - Small codebase (~17kLOC)
21  - Focus on portability, efficiency and simplicity
22  - No dependencies (not even the standard library if not wanted)
23  - Fully skinnable and customizable
24  - Low memory footprint with total memory control if needed or wanted
25  - UTF-8 support
26  - No global or hidden state
27  - Customizable library modules (you can compile and use only what you need)
28  - Optional font baker and vertex buffer output
29 
30 USAGE:
31  This library is self contained in one single header file and can be used either
32  in header only mode or in implementation mode. The header only mode is used
33  by default when included and allows including this header in other headers
34  and does not contain the actual implementation.
35 
36  The implementation mode requires to define the preprocessor macro
37  NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.:
38 
39  #define NK_IMPLEMENTATION
40  #include "nuklear.h"
41 
42  Also optionally define the symbols listed in the section "OPTIONAL DEFINES"
43  below in header and implementation mode if you want to use additional functionality
44  or need more control over the library.
45  IMPORTANT: Every time you include "nuklear.h" you have to define the same flags.
46  This is very important not doing it either leads to compiler errors
47  or even worse stack corruptions.
48 
49 FEATURES:
50  - Absolutely no platform dependend code
51  - Memory management control ranging from/to
52  - Ease of use by allocating everything from standard library
53  - Control every byte of memory inside the library
54  - Font handling control ranging from/to
55  - Use your own font implementation for everything
56  - Use this libraries internal font baking and handling API
57  - Drawing output control ranging from/to
58  - Simple shapes for more high level APIs which already have drawing capabilities
59  - Hardware accessible anti-aliased vertex buffer output
60  - Customizable colors and properties ranging from/to
61  - Simple changes to color by filling a simple color table
62  - Complete control with ability to use skinning to decorate widgets
63  - Bendable UI library with widget ranging from/to
64  - Basic widgets like buttons, checkboxes, slider, ...
65  - Advanced widget like abstract comboboxes, contextual menus,...
66  - Compile time configuration to only compile what you need
67  - Subset which can be used if you do not want to link or use the standard library
68  - Can be easily modified to only update on user input instead of frame updates
69 
70 OPTIONAL DEFINES:
71  NK_PRIVATE
72  If defined declares all functions as static, so they can only be accessed
73  inside the file that contains the implementation
74 
75  NK_INCLUDE_FIXED_TYPES
76  If defined it will include header <stdint.h> for fixed sized types
77  otherwise nuklear tries to select the correct type. If that fails it will
78  throw a compiler error and you have to select the correct types yourself.
79  <!> If used needs to be defined for implementation and header <!>
80 
81  NK_INCLUDE_DEFAULT_ALLOCATOR
82  if defined it will include header <stdlib.h> and provide additional functions
83  to use this library without caring for memory allocation control and therefore
84  ease memory management.
85  <!> Adds the standard library with malloc and free so don't define if you
86  don't want to link to the standard library <!>
87  <!> If used needs to be defined for implementation and header <!>
88 
89  NK_INCLUDE_STANDARD_IO
90  if defined it will include header <stdio.h> and provide
91  additional functions depending on file loading.
92  <!> Adds the standard library with fopen, fclose,... so don't define this
93  if you don't want to link to the standard library <!>
94  <!> If used needs to be defined for implementation and header <!>
95 
96  NK_INCLUDE_STANDARD_VARARGS
97  if defined it will include header <stdarg.h> and provide
98  additional functions depending on variable arguments
99  <!> Adds the standard library with va_list and so don't define this if
100  you don't want to link to the standard library<!>
101  <!> If used needs to be defined for implementation and header <!>
102 
103  NK_INCLUDE_VERTEX_BUFFER_OUTPUT
104  Defining this adds a vertex draw command list backend to this
105  library, which allows you to convert queue commands into vertex draw commands.
106  This is mainly if you need a hardware accessible format for OpenGL, DirectX,
107  Vulkan, Metal,...
108  <!> If used needs to be defined for implementation and header <!>
109 
110  NK_INCLUDE_FONT_BAKING
111  Defining this adds the `stb_truetype` and `stb_rect_pack` implementation
112  to this library and provides font baking and rendering.
113  If you already have font handling or do not want to use this font handler
114  you don't have to define it.
115  <!> If used needs to be defined for implementation and header <!>
116 
117  NK_INCLUDE_DEFAULT_FONT
118  Defining this adds the default font: ProggyClean.ttf into this library
119  which can be loaded into a font atlas and allows using this library without
120  having a truetype font
121  <!> Enabling this adds ~12kb to global stack memory <!>
122  <!> If used needs to be defined for implementation and header <!>
123 
124  NK_INCLUDE_COMMAND_USERDATA
125  Defining this adds a userdata pointer into each command. Can be useful for
126  example if you want to provide custom shaders depending on the used widget.
127  Can be combined with the style structures.
128  <!> If used needs to be defined for implementation and header <!>
129 
130  NK_BUTTON_TRIGGER_ON_RELEASE
131  Different platforms require button clicks occuring either on buttons being
132  pressed (up to down) or released (down to up).
133  By default this library will react on buttons being pressed, but if you
134  define this it will only trigger if a button is released.
135  <!> If used it is only required to be defined for the implementation part <!>
136 
137  NK_ZERO_COMMAND_MEMORY
138  Defining this will zero out memory for each drawing command added to a
139  drawing queue (inside nk_command_buffer_push). Zeroing command memory
140  is very useful for fast checking (using memcmp) if command buffers are
141  equal and avoid drawing frames when nothing on screen has changed since
142  previous frame.
143 
144  NK_ASSERT
145  If you don't define this, nuklear will use <assert.h> with assert().
146  <!> Adds the standard library so define to nothing of not wanted <!>
147  <!> If used needs to be defined for implementation and header <!>
148 
149  NK_BUFFER_DEFAULT_INITIAL_SIZE
150  Initial buffer size allocated by all buffers while using the default allocator
151  functions included by defining NK_INCLUDE_DEFAULT_ALLOCATOR. If you don't
152  want to allocate the default 4k memory then redefine it.
153  <!> If used needs to be defined for implementation and header <!>
154 
155  NK_MAX_NUMBER_BUFFER
156  Maximum buffer size for the conversion buffer between float and string
157  Under normal circumstances this should be more than sufficient.
158  <!> If used needs to be defined for implementation and header <!>
159 
160  NK_INPUT_MAX
161  Defines the max number of bytes which can be added as text input in one frame.
162  Under normal circumstances this should be more than sufficient.
163  <!> If used it is only required to be defined for the implementation part <!>
164 
165  NK_MEMSET
166  You can define this to 'memset' or your own memset implementation
167  replacement. If not nuklear will use its own version.
168  <!> If used it is only required to be defined for the implementation part <!>
169 
170  NK_MEMCPY
171  You can define this to 'memcpy' or your own memcpy implementation
172  replacement. If not nuklear will use its own version.
173  <!> If used it is only required to be defined for the implementation part <!>
174 
175  NK_SQRT
176  You can define this to 'sqrt' or your own sqrt implementation
177  replacement. If not nuklear will use its own slow and not highly
178  accurate version.
179  <!> If used it is only required to be defined for the implementation part <!>
180 
181  NK_SIN
182  You can define this to 'sinf' or your own sine implementation
183  replacement. If not nuklear will use its own approximation implementation.
184  <!> If used it is only required to be defined for the implementation part <!>
185 
186  NK_COS
187  You can define this to 'cosf' or your own cosine implementation
188  replacement. If not nuklear will use its own approximation implementation.
189  <!> If used it is only required to be defined for the implementation part <!>
190 
191  NK_STRTOD
192  You can define this to `strtod` or your own string to double conversion
193  implementation replacement. If not defined nuklear will use its own
194  imprecise and possibly unsafe version (does not handle nan or infinity!).
195  <!> If used it is only required to be defined for the implementation part <!>
196 
197  NK_DTOA
198  You can define this to `dtoa` or your own double to string conversion
199  implementation replacement. If not defined nuklear will use its own
200  imprecise and possibly unsafe version (does not handle nan or infinity!).
201  <!> If used it is only required to be defined for the implementation part <!>
202 
203  NK_VSNPRINTF
204  If you define `NK_INCLUDE_STANDARD_VARARGS` as well as `NK_INCLUDE_STANDARD_IO`
205  and want to be safe define this to `vsnprintf` on compilers supporting
206  later versions of C or C++. By default nuklear will check for your stdlib version
207  in C as well as compiler version in C++. if `vsnprintf` is available
208  it will define it to `vsnprintf` directly. If not defined and if you have
209  older versions of C or C++ it will be defined to `vsprintf` which is unsafe.
210  <!> If used it is only required to be defined for the implementation part <!>
211 
212  NK_BYTE
213  NK_INT16
214  NK_UINT16
215  NK_INT32
216  NK_UINT32
217  NK_SIZE_TYPE
218  NK_POINTER_TYPE
219  If you compile without NK_USE_FIXED_TYPE then a number of standard types
220  will be selected and compile time validated. If they are incorrect you can
221  define the correct types by overloading these type defines.
222 
223 CREDITS:
224  Developed by Micha Mettke and every direct or indirect contributor.
225 
226  Embeds stb_texedit, stb_truetype and stb_rectpack by Sean Barret (public domain)
227  Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license).
228 
229  Big thank you to Omar Cornut (ocornut@github) for his imgui library and
230  giving me the inspiration for this library, Casey Muratori for handmade hero
231  and his original immediate mode graphical user interface idea and Sean
232  Barret for his amazing single header libraries which restored my faith
233  in libraries and brought me to create some of my own.
234 
235 LICENSE:
236  This software is dual-licensed to the public domain and under the following
237  license: you are granted a perpetual, irrevocable license to copy, modify,
238  publish and distribute this file as you see fit.
239 */
240 #ifndef NK_NUKLEAR_H_
241 #define NK_NUKLEAR_H_
242 
243 #ifdef __cplusplus
244 extern "C" {
245 #endif
246 /*
247  * ==============================================================
248  *
249  * CONSTANTS
250  *
251  * ===============================================================
252  */
253 #define NK_UNDEFINED (-1.0f)
254 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
255 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
256 #ifndef NK_INPUT_MAX
257 #define NK_INPUT_MAX 16
258 #endif
259 #ifndef NK_MAX_NUMBER_BUFFER
260 #define NK_MAX_NUMBER_BUFFER 64
261 #endif
262 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
263 #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
264 #endif
265 /*
266  * ==============================================================
267  *
268  * HELPER
269  *
270  * ===============================================================
271  */
272 #ifndef NK_API
273  #ifdef NK_PRIVATE
274  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
275  #define NK_API static inline
276  #elif defined(__cplusplus)
277  #define NK_API static inline
278  #else
279  #define NK_API static
280  #endif
281  #else
282  #define NK_API extern
283  #endif
284 #endif
285 
286 #define NK_INTERN static
287 #define NK_STORAGE static
288 #define NK_GLOBAL static
289 
290 #define NK_FLAG(x) (1 << (x))
291 #define NK_STRINGIFY(x) #x
292 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
293 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
294 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
295 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
296 
297 #ifdef _MSC_VER
298 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
299 #else
300 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
301 #endif
302 
303 #ifndef NK_STATIC_ASSERT
304 #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
305 #endif
306 
307 #ifndef NK_FILE_LINE
308 #ifdef _MSC_VER
309 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
310 #else
311 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
312 #endif
313 #endif
314 
315 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
316 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
317 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
318 /*
319  * ===============================================================
320  *
321  * BASIC
322  *
323  * ===============================================================
324  */
325 #ifdef NK_INCLUDE_FIXED_TYPES
326  #include <stdint.h>
327  #define NK_INT8 int8_t
328  #define NK_UINT8 uint8_t
329  #define NK_INT16 int16_t
330  #define NK_UINT16 uint16_t
331  #define NK_INT32 int32_t
332  #define NK_UINT32 uint32_t
333  #define NK_SIZE_TYPE uintptr_t
334  #define NK_POINTER_TYPE uintptr_t
335 #else
336  #ifndef NK_INT8
337  #define NK_INT8 char
338  #endif
339  #ifndef NK_UINT8
340  #define NK_UINT8 unsigned char
341  #endif
342  #ifndef NK_INT16
343  #define NK_INT16 signed short
344  #endif
345  #ifndef NK_UINT16
346  #define NK_UINT16 unsigned short
347  #endif
348  #ifndef NK_INT32
349  #if defined(_MSC_VER)
350  #define NK_INT32 __int32
351  #else
352  #define NK_INT32 signed int
353  #endif
354  #endif
355  #ifndef NK_UINT32
356  #if defined(_MSC_VER)
357  #define NK_UINT32 unsigned __int32
358  #else
359  #define NK_UINT32 unsigned int
360  #endif
361  #endif
362  #ifndef NK_SIZE_TYPE
363  #if defined(_WIN64) && defined(_MSC_VER)
364  #define NK_SIZE_TYPE unsigned __int64
365  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
366  #define NK_SIZE_TYPE unsigned __int32
367  #elif defined(__GNUC__) || defined(__clang__)
368  #if defined(__x86_64__) || defined(__ppc64__)
369  #define NK_SIZE_TYPE unsigned long
370  #else
371  #define NK_SIZE_TYPE unsigned int
372  #endif
373  #else
374  #define NK_SIZE_TYPE unsigned long
375  #endif
376  #endif
377  #ifndef NK_POINTER_TYPE
378  #if defined(_WIN64) && defined(_MSC_VER)
379  #define NK_POINTER_TYPE unsigned __int64
380  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
381  #define NK_POINTER_TYPE unsigned __int32
382  #elif defined(__GNUC__) || defined(__clang__)
383  #if defined(__x86_64__) || defined(__ppc64__)
384  #define NK_POINTER_TYPE unsigned long
385  #else
386  #define NK_POINTER_TYPE unsigned int
387  #endif
388  #else
389  #define NK_POINTER_TYPE unsigned long
390  #endif
391  #endif
392 #endif
393 
394 typedef NK_INT8 nk_char;
399 typedef NK_INT32 nk_int;
403 
404 typedef nk_uint nk_hash;
405 typedef nk_uint nk_flags;
406 typedef nk_uint nk_rune;
407 
408 /* Make sure correct type size:
409  * This will fire with a negative subscript error if the type sizes
410  * are set incorrectly by the compiler, and compile out if not */
411 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
412 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
413 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
414 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
415 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
416 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
417 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
418 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
419 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
420 
421 /* ============================================================================
422  *
423  * API
424  *
425  * =========================================================================== */
426 struct nk_buffer;
427 struct nk_allocator;
428 struct nk_command_buffer;
429 struct nk_draw_command;
430 struct nk_convert_config;
431 struct nk_style_item;
432 struct nk_text_edit;
433 struct nk_draw_list;
434 struct nk_user_font;
435 struct nk_panel;
436 struct nk_context;
437 struct nk_draw_vertex_layout_element;
438 struct nk_style_button;
439 struct nk_style_toggle;
440 struct nk_style_selectable;
441 struct nk_style_slide;
442 struct nk_style_progress;
443 struct nk_style_scrollbar;
444 struct nk_style_edit;
445 struct nk_style_property;
446 struct nk_style_chart;
447 struct nk_style_combo;
448 struct nk_style_tab;
450 struct nk_style_window;
451 
453 struct nk_color {nk_byte r,g,b,a;};
454 struct nk_colorf {float r,g,b,a;};
455 struct nk_vec2 {float x,y;};
456 struct nk_vec2i {short x, y;};
457 struct nk_rect {float x,y,w,h;};
458 struct nk_recti {short x,y,w,h;};
459 typedef char nk_glyph[NK_UTF_SIZE];
460 typedef union {void *ptr; int id;} nk_handle;
461 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
462 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
463 struct nk_scroll {nk_uint x, y;};
464 
477 
478 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
479 typedef void (*nk_plugin_free)(nk_handle, void *old);
480 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
481 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
482 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
483 
484 struct nk_allocator {
485  nk_handle userdata;
488 };
504 };
505 /* =============================================================================
506  *
507  * CONTEXT
508  *
509  * =============================================================================*/
510 /* Contexts are the main entry point and the majestro of nuklear and contain all required state.
511  * They are used for window, memory, input, style, stack, commands and time management and need
512  * to be passed into all nuklear GUI specific functions.
513  *
514  * Usage
515  * -------------------
516  * To use a context it first has to be initialized which can be achieved by calling
517  * one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`.
518  * Each takes in a font handle and a specific way of handling memory. Memory control
519  * hereby ranges from standard library to just specifing a fixed sized block of memory
520  * which nuklear has to manage itself from.
521  *
522  * struct nk_context ctx;
523  * nk_init_xxx(&ctx, ...);
524  * while (1) {
525  * [...]
526  * nk_clear(&ctx);
527  * }
528  * nk_free(&ctx);
529  *
530  * Reference
531  * -------------------
532  * nk_init_default - Initializes context with standard library memory alloction (malloc,free)
533  * nk_init_fixed - Initializes context from single fixed size memory block
534  * nk_init - Initializes context with memory allocator callbacks for alloc and free
535  * nk_init_custom - Initializes context from two buffers. One for draw commands the other for window/panel/table allocations
536  * nk_clear - Called at the end of the frame to reset and prepare the context for the next frame
537  * nk_free - Shutdown and free all memory allocated inside the context
538  * nk_set_user_data - Utility function to pass user data to draw command
539  */
540 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
541 /* nk_init_default - Initializes a `nk_context` struct with a default standard library allocator.
542  * Should be used if you don't want to be bothered with memory management in nuklear.
543  * Parameters:
544  * @ctx must point to an either stack or heap allocated `nk_context` struct
545  * @font must point to a previously initialized font handle for more info look at font documentation
546  * Return values:
547  * true(1) on success
548  * false(0) on failure */
549 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*);
550 #endif
551 /* nk_init_fixed - Initializes a `nk_context` struct from a single fixed size memory block
552  * Should be used if you want complete control over nuklears memory management.
553  * Especially recommended for system with little memory or systems with virtual memory.
554  * For the later case you can just allocate for example 16MB of virtual memory
555  * and only the required amount of memory will actually be commited.
556  * IMPORTANT: make sure the passed memory block is aligned correctly for `nk_draw_commands`
557  * Parameters:
558  * @ctx must point to an either stack or heap allocated `nk_context` struct
559  * @memory must point to a previously allocated memory block
560  * @size must contain the total size of @memory
561  * @font must point to a previously initialized font handle for more info look at font documentation
562  * Return values:
563  * true(1) on success
564  * false(0) on failure */
565 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
566 /* nk_init - Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate
567  * memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation
568  * interface to nuklear. Can be useful for cases like monitoring memory consumption.
569  * Parameters:
570  * @ctx must point to an either stack or heap allocated `nk_context` struct
571  * @alloc must point to a previously allocated memory allocator
572  * @font must point to a previously initialized font handle for more info look at font documentation
573  * Return values:
574  * true(1) on success
575  * false(0) on failure */
576 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
577 /* nk_init_custom - Initializes a `nk_context` struct from two different either fixed or growing
578  * buffers. The first buffer is for allocating draw commands while the second buffer is
579  * used for allocating windows, panels and state tables.
580  * Parameters:
581  * @ctx must point to an either stack or heap allocated `nk_context` struct
582  * @cmds must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into
583  * @pool must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables
584  * @font must point to a previously initialized font handle for more info look at font documentation
585  * Return values:
586  * true(1) on success
587  * false(0) on failure */
588 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
589 /* nk_clear - Resets the context state at the end of the frame. This includes mostly
590  * garbage collector tasks like removing windows or table not called and therefore
591  * used anymore.
592  * Parameters:
593  * @ctx must point to a previously initialized `nk_context` struct */
594 NK_API void nk_clear(struct nk_context*);
595 /* nk_free - Frees all memory allocated by nuklear. Not needed if context was
596  * initialized with `nk_init_fixed`.
597  * Parameters:
598  * @ctx must point to a previously initialized `nk_context` struct */
599 NK_API void nk_free(struct nk_context*);
600 #ifdef NK_INCLUDE_COMMAND_USERDATA
601 /* nk_set_user_data - Sets the currently passed userdata passed down into each draw command.
602  * Parameters:
603  * @ctx must point to a previously initialized `nk_context` struct
604  * @data handle with either pointer or index to be passed into every draw commands */
605 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
606 #endif
607 /* =============================================================================
608  *
609  * INPUT
610  *
611  * =============================================================================*/
612 /* The input API is responsible for holding the current input state composed of
613  * mouse, key and text input states.
614  * It is worth noting that no direct os or window handling is done in nuklear.
615  * Instead all input state has to be provided by platform specific code. This in one hand
616  * expects more work from the user and complicates usage but on the other hand
617  * provides simple abstraction over a big number of platforms, libraries and other
618  * already provided functionality.
619  *
620  * Usage
621  * -------------------
622  * Input state needs to be provided to nuklear by first calling `nk_input_begin`
623  * which resets internal state like delta mouse position and button transistions.
624  * After `nk_input_begin` all current input state needs to be provided. This includes
625  * mouse motion, button and key pressed and released, text input and scrolling.
626  * Both event- or state-based input handling are supported by this API
627  * and should work without problems. Finally after all input state has been
628  * mirrored `nk_input_end` needs to be called to finish input process.
629  *
630  * struct nk_context ctx;
631  * nk_init_xxx(&ctx, ...);
632  * while (1) {
633  * Event evt;
634  * nk_input_begin(&ctx);
635  * while (GetEvent(&evt)) {
636  * if (evt.type == MOUSE_MOVE)
637  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
638  * else if (evt.type == ...) {
639  * ...
640  * }
641  * }
642  * nk_input_end(&ctx);
643  * [...]
644  * nk_clear(&ctx);
645  * }
646  * nk_free(&ctx);
647  *
648  * Reference
649  * -------------------
650  * nk_input_begin - Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls
651  * nk_input_motion - Mirrors mouse cursor position
652  * nk_input_key - Mirrors key state with either pressed or released
653  * nk_input_button - Mirrors mouse button state with either pressed or released
654  * nk_input_scroll - Mirrors mouse scroll values
655  * nk_input_char - Adds a single ASCII text character into an internal text buffer
656  * nk_input_glyph - Adds a single multi-byte UTF-8 character into an internal text buffer
657  * nk_input_unicode - Adds a single unicode rune into an internal text buffer
658  * nk_input_end - Ends the input mirroring process by calculating state changes. Don't call any `nk_input_xxx` function referenced above after this call
659  */
660 enum nk_keys {
675  /* Shortcuts: text field */
688  /* Shortcuts: scrollbar */
694 };
701 };
702 /* nk_input_begin - Begins the input mirroring process by resetting text, scroll
703  * mouse previous mouse position and movement as well as key state transistions,
704  * Parameters:
705  * @ctx must point to an previously initialized `nk_context` struct */
706 NK_API void nk_input_begin(struct nk_context*);
707 /* nk_input_motion - Mirros current mouse position to nuklear
708  * Parameters:
709  * @ctx must point to an previously initialized `nk_context` struct
710  * @x must constain an integer describing the current mouse cursor x-position
711  * @y must constain an integer describing the current mouse cursor y-position */
712 NK_API void nk_input_motion(struct nk_context*, int x, int y);
713 /* nk_input_key - Mirros state of a specific key to nuklear
714  * Parameters:
715  * @ctx must point to an previously initialized `nk_context` struct
716  * @key must be any value specified in enum `nk_keys` that needs to be mirrored
717  * @down must be 0 for key is up and 1 for key is down */
718 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down);
719 /* nk_input_button - Mirros the state of a specific mouse button to nuklear
720  * Parameters:
721  * @ctx must point to an previously initialized `nk_context` struct
722  * @nk_buttons must be any value specified in enum `nk_buttons` that needs to be mirrored
723  * @x must constain an integer describing mouse cursor x-position on click up/down
724  * @y must constain an integer describing mouse cursor y-position on click up/down
725  * @down must be 0 for key is up and 1 for key is down */
726 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down);
727 /* nk_input_char - Copies a single ASCII character into an internal text buffer
728  * This is basically a helper function to quickly push ASCII characters into
729  * nuklear. Note that you can only push up to NK_INPUT_MAX bytes into
730  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
731  * Parameters:
732  * @ctx must point to an previously initialized `nk_context` struct
733  * @c must be a single ASCII character preferable one that can be printed */
734 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
735 /* nk_input_char - Copies a single ASCII character into an internal text buffer
736  * This is basically a helper function to quickly push ASCII characters into
737  * nuklear. Note that you can only push up to NK_INPUT_MAX bytes into
738  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
739  * Parameters:
740  * @ctx must point to an previously initialized `nk_context` struct
741  * @c must be a single ASCII character preferable one that can be printed */
742 NK_API void nk_input_char(struct nk_context*, char);
743 /* nk_input_unicode - Converts a encoded unicode rune into UTF-8 and copies the result
744  * into an internal text buffer.
745  * Note that you can only push up to NK_INPUT_MAX bytes into
746  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
747  * Parameters:
748  * @ctx must point to an previously initialized `nk_context` struct
749  * @glyph UTF-32 uncode codepoint */
750 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
751 /* nk_input_unicode - Converts a unicode rune into UTF-8 and copies the result
752  * into an internal text buffer.
753  * Note that you can only push up to NK_INPUT_MAX bytes into
754  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
755  * Parameters:
756  * @ctx must point to an previously initialized `nk_context` struct
757  * @glyph UTF-32 uncode codepoint */
758 NK_API void nk_input_unicode(struct nk_context*, nk_rune);
759 /* nk_input_end - End the input mirroring process by resetting mouse grabbing
760  * state to ensure the mouse cursor is not grabbed indefinitely.
761  * Parameters:
762  * @ctx must point to an previously initialized `nk_context` struct */
763 NK_API void nk_input_end(struct nk_context*);
764 /* =============================================================================
765  *
766  * DRAWING
767  *
768  * =============================================================================*/
769 /* This library was designed to be render backend agnostic so it does
770  * not draw anything to screen directly. Instead all drawn shapes, widgets
771  * are made of, are buffered into memory and make up a command queue.
772  * Each frame therefore fills the command buffer with draw commands
773  * that then need to be executed by the user and his own render backend.
774  * After that the command buffer needs to be cleared and a new frame can be
775  * started. It is probably important to note that the command buffer is the main
776  * drawing API and the optional vertex buffer API only takes this format and
777  * converts it into a hardware accessible format.
778  *
779  * Usage
780  * -------------------
781  * To draw all draw commands accumulated over a frame you need your own render
782  * backend able to draw a number of 2D primitives. This includes at least
783  * filled and stroked rectangles, circles, text, lines, triangles and scissors.
784  * As soon as this criterion is met you can iterate over each draw command
785  * and execute each draw command in a interpreter like fashion:
786  *
787  * const struct nk_command *cmd = 0;
788  * nk_foreach(cmd, &ctx) {
789  * switch (cmd->type) {
790  * case NK_COMMAND_LINE:
791  * your_draw_line_function(...)
792  * break;
793  * case NK_COMMAND_RECT
794  * your_draw_rect_function(...)
795  * break;
796  * case ...:
797  * [...]
798  * }
799  *
800  * In program flow context draw commands need to be executed after input has been
801  * gathered and the complete UI with windows and their contained widgets have
802  * been executed and before calling `nk_clear` which frees all previously
803  * allocated draw commands.
804  *
805  * struct nk_context ctx;
806  * nk_init_xxx(&ctx, ...);
807  * while (1) {
808  * Event evt;
809  * nk_input_begin(&ctx);
810  * while (GetEvent(&evt)) {
811  * if (evt.type == MOUSE_MOVE)
812  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
813  * else if (evt.type == [...]) {
814  * [...]
815  * }
816  * }
817  * nk_input_end(&ctx);
818  *
819  * [...]
820  *
821  * const struct nk_command *cmd = 0;
822  * nk_foreach(cmd, &ctx) {
823  * switch (cmd->type) {
824  * case NK_COMMAND_LINE:
825  * your_draw_line_function(...)
826  * break;
827  * case NK_COMMAND_RECT
828  * your_draw_rect_function(...)
829  * break;
830  * case ...:
831  * [...]
832  * }
833  * nk_clear(&ctx);
834  * }
835  * nk_free(&ctx);
836  *
837  * You probably noticed that you have to draw all of the UI each frame which is
838  * quite wasteful. While the actual UI updating loop is quite fast rendering
839  * without actually needing it is not. So there are multiple things you could do.
840  *
841  * First is only update on input. This of course is only an option if your
842  * application only depends on the UI and does not require any outside calculations.
843  * If you actually only update on input make sure to update the UI two times each
844  * frame and call `nk_clear` directly after the first pass and only draw in
845  * the second pass.
846  *
847  * struct nk_context ctx;
848  * nk_init_xxx(&ctx, ...);
849  * while (1) {
850  * [...wait for input ]
851  *
852  * [...do two UI passes ...]
853  * do_ui(...)
854  * nk_clear(&ctx);
855  * do_ui(...)
856  *
857  * const struct nk_command *cmd = 0;
858  * nk_foreach(cmd, &ctx) {
859  * switch (cmd->type) {
860  * case NK_COMMAND_LINE:
861  * your_draw_line_function(...)
862  * break;
863  * case NK_COMMAND_RECT
864  * your_draw_rect_function(...)
865  * break;
866  * case ...:
867  * [...]
868  * }
869  * nk_clear(&ctx);
870  * }
871  * nk_free(&ctx);
872  *
873  * The second probably more applicable trick is to only draw if anything changed.
874  * It is not really useful for applications with continous draw loop but
875  * quite useful for desktop applications. To actually get nuklear to only
876  * draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and
877  * allocate a memory buffer that will store each unique drawing output.
878  * After each frame you compare the draw command memory inside the library
879  * with your allocated buffer by memcmp. If memcmp detects differences
880  * you have to copy the nuklears command buffer into the allocated buffer
881  * and then draw like usual (this example uses fixed memory but you could
882  * use dynamically allocated memory).
883  *
884  * [... other defines ...]
885  * #define NK_ZERO_COMMAND_MEMORY
886  * #include "nuklear.h"
887  *
888  * struct nk_context ctx;
889  * void *last = calloc(1,64*1024);
890  * void *buf = calloc(1,64*1024);
891  * nk_init_fixed(&ctx, buf, 64*1024);
892  * while (1) {
893  * [...input...]
894  * [...ui...]
895  *
896  * void *cmds = nk_buffer_memory(&ctx.memory);
897  * if (memcmp(cmds, last, ctx.memory.allocated)) {
898  * memcpy(last,cmds,ctx.memory.allocated);
899  * const struct nk_command *cmd = 0;
900  * nk_foreach(cmd, &ctx) {
901  * switch (cmd->type) {
902  * case NK_COMMAND_LINE:
903  * your_draw_line_function(...)
904  * break;
905  * case NK_COMMAND_RECT
906  * your_draw_rect_function(...)
907  * break;
908  * case ...:
909  * [...]
910  * }
911  * }
912  * }
913  * nk_clear(&ctx);
914  * }
915  * nk_free(&ctx);
916  *
917  * Finally while using draw commands makes sense for higher abstracted platforms like
918  * X11 and Win32 or drawing libraries it is often desirable to use graphics
919  * hardware directly. Therefore it is possible to just define
920  * `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output.
921  * To access the vertex output you first have to convert all draw commands into
922  * vertexes by calling `nk_convert` which takes in your prefered vertex format.
923  * After successfully converting all draw commands just iterate over and execute all
924  * vertex draw commands:
925  *
926  * struct nk_convert_config cfg = {};
927  * static const struct nk_draw_vertex_layout_element vertex_layout[] = {
928  * {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)},
929  * {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)},
930  * {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)},
931  * {NK_VERTEX_LAYOUT_END}
932  * };
933  * cfg.shape_AA = NK_ANTI_ALIASING_ON;
934  * cfg.line_AA = NK_ANTI_ALIASING_ON;
935  * cfg.vertex_layout = vertex_layout;
936  * cfg.vertex_size = sizeof(struct your_vertex);
937  * cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex);
938  * cfg.circle_segment_count = 22;
939  * cfg.curve_segment_count = 22;
940  * cfg.arc_segment_count = 22;
941  * cfg.global_alpha = 1.0f;
942  * cfg.null = dev->null;
943  *
944  * struct nk_buffer cmds, verts, idx;
945  * nk_buffer_init_default(&cmds);
946  * nk_buffer_init_default(&verts);
947  * nk_buffer_init_default(&idx);
948  * nk_convert(&ctx, &cmds, &verts, &idx, &cfg);
949  * nk_draw_foreach(cmd, &ctx, &cmds) {
950  * if (!cmd->elem_count) continue;
951  * [...]
952  * }
953  * nk_buffer_free(&cms);
954  * nk_buffer_free(&verts);
955  * nk_buffer_free(&idx);
956  *
957  * Reference
958  * -------------------
959  * nk__begin - Returns the first draw command in the context draw command list to be drawn
960  * nk__next - Increments the draw command iterator to the next command inside the context draw command list
961  * nk_foreach - Iteratates over each draw command inside the context draw command list
962  *
963  * nk_convert - Converts from the abstract draw commands list into a hardware accessable vertex format
964  * nk__draw_begin - Returns the first vertex command in the context vertex draw list to be executed
965  * nk__draw_next - Increments the vertex command iterator to the next command inside the context vertex command list
966  * nk__draw_end - Returns the end of the vertex draw list
967  * nk_draw_foreach - Iterates over each vertex draw command inside the vertex draw list
968  */
976 };
978  nk_handle texture; /* texture handle to a texture with a white pixel */
979  struct nk_vec2 uv; /* coordinates to a white pixel in the texture */
980 };
982  float global_alpha; /* global alpha value */
983  enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
984  enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
985  unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
986  unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
987  unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
988  struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
989  const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
990  nk_size vertex_size; /* sizeof one vertex for vertex packing */
991  nk_size vertex_alignment; /* vertex alignment: Can be optained by NK_ALIGNOF */
992 };
993 /* nk__begin - Returns a draw command list iterator to iterate all draw
994  * commands accumulated over one frame.
995  * Parameters:
996  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
997  * Return values:
998  * draw command pointer pointing to the first command inside the draw command list */
999 NK_API const struct nk_command* nk__begin(struct nk_context*);
1000 /* nk__next - Returns a draw command list iterator to iterate all draw
1001  * Parameters:
1002  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1003  * @cmd must point to an previously a draw command either returned by `nk__begin` or `nk__next`
1004  * Return values:
1005  * draw command pointer pointing to the next command inside the draw command list */
1006 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1007 /* nk_foreach - Iterates over each draw command inside the context draw command list
1008  * Parameters:
1009  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1010  * @cmd pointer initialized to NULL */
1011 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
1012 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
1013 /* nk_convert - converts all internal draw command into vertex draw commands and fills
1014  * three buffers with vertexes, vertex draw commands and vertex indicies. The vertex format
1015  * as well as some other configuration values have to be configurated by filling out a
1016  * `nk_convert_config` struct.
1017  * Parameters:
1018  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1019  * @cmds must point to a previously initialized buffer to hold converted vertex draw commands
1020  * @vertices must point to a previously initialized buffer to hold all produced verticies
1021  * @elements must point to a previously initialized buffer to hold all procudes vertex indicies
1022  * @config must point to a filled out `nk_config` struct to configure the conversion process
1023  * Returns:
1024  * returns NK_CONVERT_SUCCESS on success and a enum nk_convert_result error values if not */
1025 NK_API nk_flags nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
1026 /* nk__draw_begin - Returns a draw vertex command buffer iterator to iterate each the vertex draw command buffer
1027  * Parameters:
1028  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1029  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1030  * Return values:
1031  * vertex draw command pointer pointing to the first command inside the vertex draw command buffer */
1032 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1033 /* nk__draw_end - Returns the vertex draw command at the end of the vertex draw command buffer
1034  * Parameters:
1035  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1036  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1037  * Return values:
1038  * vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer */
1039 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
1040 /* nk__draw_next - Increments the the vertex draw command buffer iterator
1041  * Parameters:
1042  * @cmd must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command
1043  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1044  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1045  * Return values:
1046  * vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer */
1047 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1048 /* nk_draw_foreach - Iterates over each vertex draw command inside a vertex draw command buffer
1049  * Parameters:
1050  * @cmd nk_draw_command pointer set to NULL
1051  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1052  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame */
1053 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
1054 #endif
1055 /* =============================================================================
1056  *
1057  * WINDOW
1058  *
1059  * =============================================================================
1060  * Windows are the main persistent state used inside nuklear and are life time
1061  * controlled by simply "retouching" (i.e. calling) each window each frame.
1062  * All widgets inside nuklear can only be added inside function pair `nk_begin_xxx`
1063  * and `nk_end`. Calling any widgets outside these two functions will result in an
1064  * assert in debug or no state change in release mode.
1065  *
1066  * Each window holds frame persistent state like position, size, flags, state tables,
1067  * and some garbage collected internal persistent widget state. Each window
1068  * is linked into a window stack list which determines the drawing and overlapping
1069  * order. The topmost window thereby is the currently active window.
1070  *
1071  * To change window position inside the stack occurs either automatically by
1072  * user input by being clicked on or programatically by calling `nk_window_focus`.
1073  * Windows by default are visible unless explicitly being defined with flag
1074  * `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag
1075  * `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling
1076  * `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.
1077  *
1078  * Usage
1079  * -------------------
1080  * To create and keep a window you have to call one of the two `nk_begin_xxx`
1081  * functions to start window declarations and `nk_end` at the end. Furthermore it
1082  * is recommended to check the return value of `nk_begin_xxx` and only process
1083  * widgets inside the window if the value is not 0. Either way you have to call
1084  * `nk_end` at the end of window declarations. Furthmore do not attempt to
1085  * nest `nk_begin_xxx` calls which will hopefully result in an assert or if not
1086  * in a segmation fault.
1087  *
1088  * if (nk_begin_xxx(...) {
1089  * [... widgets ...]
1090  * }
1091  * nk_end(ctx);
1092  *
1093  * In the grand concept window and widget declarations need to occur after input
1094  * handling and before drawing to screen. Not doing so can result in higher
1095  * latency or at worst invalid behavior. Furthermore make sure that `nk_clear`
1096  * is called at the end of the frame. While nuklears default platform backends
1097  * already call `nk_clear` for you if you write your own backend not calling
1098  * `nk_clear` can cause asserts or even worse undefined behavior.
1099  *
1100  * struct nk_context ctx;
1101  * nk_init_xxx(&ctx, ...);
1102  * while (1) {
1103  * Event evt;
1104  * nk_input_begin(&ctx);
1105  * while (GetEvent(&evt)) {
1106  * if (evt.type == MOUSE_MOVE)
1107  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
1108  * else if (evt.type == [...]) {
1109  * nk_input_xxx(...);
1110  * }
1111  * }
1112  * nk_input_end(&ctx);
1113  *
1114  * if (nk_begin_xxx(...) {
1115  * [...]
1116  * }
1117  * nk_end(ctx);
1118  *
1119  * const struct nk_command *cmd = 0;
1120  * nk_foreach(cmd, &ctx) {
1121  * case NK_COMMAND_LINE:
1122  * your_draw_line_function(...)
1123  * break;
1124  * case NK_COMMAND_RECT
1125  * your_draw_rect_function(...)
1126  * break;
1127  * case ...:
1128  * [...]
1129  * }
1130  * nk_clear(&ctx);
1131  * }
1132  * nk_free(&ctx);
1133  *
1134  * Reference
1135  * -------------------
1136  * nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1137  * nk_begin_titled - extended window start with seperated title and identifier to allow multiple windows with same name but not title
1138  * nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup
1139  *
1140  * nk_window_find - finds and returns the window with give name
1141  * nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window.
1142  * nk_window_get_position - returns the position of the currently processed window
1143  * nk_window_get_size - returns the size with width and height of the currently processed window
1144  * nk_window_get_width - returns the width of the currently processed window
1145  * nk_window_get_height - returns the height of the currently processed window
1146  * nk_window_get_panel - returns the underlying panel which contains all processing state of the currnet window
1147  * nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window
1148  * nk_window_get_content_region_min - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1149  * nk_window_get_content_region_max - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1150  * nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window
1151  * nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets
1152  *
1153  * nk_window_has_focus - returns if the currently processed window is currently active
1154  * nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed
1155  * nk_window_is_closed - returns if the currently processed window was closed
1156  * nk_window_is_hidden - returns if the currently processed window was hidden
1157  * nk_window_is_active - same as nk_window_has_focus for some reason
1158  * nk_window_is_hovered - returns if the currently processed window is currently being hovered by mouse
1159  * nk_window_is_any_hovered - return if any wndow currently hovered
1160  * nk_item_is_any_active - returns if any window or widgets is currently hovered or active
1161  *
1162  * nk_window_set_bounds - updates position and size of the currently processed window
1163  * nk_window_set_position - updates position of the currently process window
1164  * nk_window_set_size - updates the size of the currently processed window
1165  * nk_window_set_focus - set the currently processed window as active window
1166  *
1167  * nk_window_close - closes the window with given window name which deletes the window at the end of the frame
1168  * nk_window_collapse - collapses the window with given window name
1169  * nk_window_collapse_if - collapses the window with given window name if the given condition was met
1170  * nk_window_show - hides a visible or reshows a hidden window
1171  * nk_window_show_if - hides/shows a window depending on condition
1172  */
1174  NK_WINDOW_BORDER = NK_FLAG(0), /* Draws a border around the window to visually separate window from the background */
1175  NK_WINDOW_MOVABLE = NK_FLAG(1), /* The movable flag indicates that a window can be moved by user input or by dragging the window header */
1176  NK_WINDOW_SCALABLE = NK_FLAG(2), /* The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window */
1177  NK_WINDOW_CLOSABLE = NK_FLAG(3), /* adds a closable icon into the header */
1178  NK_WINDOW_MINIMIZABLE = NK_FLAG(4), /* adds a minimize icon into the header */
1179  NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5), /* Removes the scrollbar from the window */
1180  NK_WINDOW_TITLE = NK_FLAG(6), /* Forces a header at the top at the window showing the title */
1181  NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7), /* Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame */
1182  NK_WINDOW_BACKGROUND = NK_FLAG(8), /* Always keep window in the background */
1183  NK_WINDOW_SCALE_LEFT = NK_FLAG(9), /* Puts window scaler in the left-ottom corner instead right-bottom*/
1184  NK_WINDOW_NO_INPUT = NK_FLAG(10) /* Prevents window of scaling, moving or getting focus */
1185 };
1186 /* nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1187  * Parameters:
1188  * @ctx must point to an previously initialized `nk_context` struct
1189  * @title window title and identifier. Needs to be persitent over frames to identify the window
1190  * @bounds initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
1191  * @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors
1192  * Return values:
1193  * returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise for example if minimized `*/
1194 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1195 /* nk_begin_titled - extended window start with seperated title and identifier to allow multiple windows with same name but not title
1196  * Parameters:
1197  * @ctx must point to an previously initialized `nk_context` struct
1198  * @name window identifier. Needs to be persitent over frames to identify the window
1199  * @title window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set
1200  * @bounds initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
1201  * @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors
1202  * Return values:
1203  * returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise `*/
1204 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1205 /* nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup.
1206  * All widget calls after this functions will result in asserts or no state changes
1207  * Parameters:
1208  * @ctx must point to an previously initialized `nk_context` struct */
1209 NK_API void nk_end(struct nk_context *ctx);
1210 /* nk_window_find - finds and returns the window with give name
1211  * Parameters:
1212  * @ctx must point to an previously initialized `nk_context` struct
1213  * @name window identifier
1214  * Return values:
1215  * returns a `nk_window` struct pointing to the idified window or 0 if no window with given name was found */
1216 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
1217 /* nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window.
1218  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1219  * Parameters:
1220  * @ctx must point to an previously initialized `nk_context` struct
1221  * Return values:
1222  * returns a `nk_rect` struct with window upper left position and size */
1224 /* nk_window_get_position - returns the position of the currently processed window.
1225  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1226  * Parameters:
1227  * @ctx must point to an previously initialized `nk_context` struct
1228  * Return values:
1229  * returns a `nk_vec2` struct with window upper left position */
1231 /* nk_window_get_size - returns the size with width and height of the currently processed window.
1232  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1233  * Parameters:
1234  * @ctx must point to an previously initialized `nk_context` struct
1235  * Return values:
1236  * returns a `nk_vec2` struct with window size */
1238 /* nk_window_get_width - returns the width of the currently processed window.
1239  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1240  * Parameters:
1241  * @ctx must point to an previously initialized `nk_context` struct
1242  * Return values:
1243  * returns the window width */
1244 NK_API float nk_window_get_width(const struct nk_context*);
1245 /* nk_window_get_height - returns the height of the currently processed window.
1246  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1247  * Parameters:
1248  * @ctx must point to an previously initialized `nk_context` struct
1249  * Return values:
1250  * returns the window height */
1251 NK_API float nk_window_get_height(const struct nk_context*);
1252 /* nk_window_get_panel - returns the underlying panel which contains all processing state of the currnet window.
1253  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1254  * Parameters:
1255  * @ctx must point to an previously initialized `nk_context` struct
1256  * Return values:
1257  * returns a pointer to window internal `nk_panel` state. DO NOT keep this pointer around it is only valid until `nk_end` */
1259 /* nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window.
1260  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1261  * Parameters:
1262  * @ctx must point to an previously initialized `nk_context` struct
1263  * Return values:
1264  * returns `nk_rect` struct with screen position and size (no scrollbar offset) of the visible space inside the current window */
1266 /* nk_window_get_content_region_min - returns the upper left position of the currently visible and non-clipped space inside the currently processed window.
1267  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1268  * Parameters:
1269  * @ctx must point to an previously initialized `nk_context` struct
1270  * Return values:
1271  * returns `nk_vec2` struct with upper left screen position (no scrollbar offset) of the visible space inside the current window */
1273 /* nk_window_get_content_region_max - returns the lower right screen position of the currently visible and non-clipped space inside the currently processed window.
1274  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1275  * Parameters:
1276  * @ctx must point to an previously initialized `nk_context` struct
1277  * Return values:
1278  * returns `nk_vec2` struct with lower right screen position (no scrollbar offset) of the visible space inside the current window */
1280 /* nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window
1281  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1282  * Parameters:
1283  * @ctx must point to an previously initialized `nk_context` struct
1284  * Return values:
1285  * returns `nk_vec2` struct with size the visible space inside the current window */
1287 /* nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets
1288  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1289  * Parameters:
1290  * @ctx must point to an previously initialized `nk_context` struct
1291  * Return values:
1292  * returns a pointer to window internal `nk_command_buffer` struct used as drawing canvas. Can be used to do custom drawing */
1294 /* nk_window_has_focus - returns if the currently processed window is currently active
1295  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1296  * Parameters:
1297  * @ctx must point to an previously initialized `nk_context` struct
1298  * Return values:
1299  * returns 0 if current window is not active or 1 if it is */
1300 NK_API int nk_window_has_focus(const struct nk_context*);
1301 /* nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed
1302  * Parameters:
1303  * @ctx must point to an previously initialized `nk_context` struct
1304  * @name of window you want to check is collapsed
1305  * Return values:
1306  * returns 1 if current window is minimized and 0 if window not found or is not minimized */
1307 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
1308 /* nk_window_is_closed - returns if the window with given name was closed by calling `nk_close`
1309  * Parameters:
1310  * @ctx must point to an previously initialized `nk_context` struct
1311  * @name of window you want to check is closed
1312  * Return values:
1313  * returns 1 if current window was closed or 0 window not found or not closed */
1314 NK_API int nk_window_is_closed(struct nk_context*, const char*);
1315 /* nk_window_is_hidden - returns if the window with given name is hidden
1316  * Parameters:
1317  * @ctx must point to an previously initialized `nk_context` struct
1318  * @name of window you want to check is hidden
1319  * Return values:
1320  * returns 1 if current window is hidden or 0 window not found or visible */
1321 NK_API int nk_window_is_hidden(struct nk_context*, const char*);
1322 /* nk_window_is_active - same as nk_window_has_focus for some reason
1323  * Parameters:
1324  * @ctx must point to an previously initialized `nk_context` struct
1325  * @name of window you want to check is hidden
1326  * Return values:
1327  * returns 1 if current window is active or 0 window not found or not active */
1328 NK_API int nk_window_is_active(struct nk_context*, const char*);
1329 /* nk_window_is_hovered - return if the current window is being hovered
1330  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1331  * Parameters:
1332  * @ctx must point to an previously initialized `nk_context` struct
1333  * Return values:
1334  * returns 1 if current window is hovered or 0 otherwise */
1336 /* nk_window_is_any_hovered - returns if the any window is being hovered
1337  * Parameters:
1338  * @ctx must point to an previously initialized `nk_context` struct
1339  * Return values:
1340  * returns 1 if any window is hovered or 0 otherwise */
1342 /* nk_item_is_any_active - returns if the any window is being hovered or any widget is currently active.
1343  * Can be used to decide if input should be processed by UI or your specific input handling.
1344  * Example could be UI and 3D camera to move inside a 3D space.
1345  * Parameters:
1346  * @ctx must point to an previously initialized `nk_context` struct
1347  * Return values:
1348  * returns 1 if any window is hovered or any item is active or 0 otherwise */
1350 /* nk_window_set_bounds - updates position and size of the currently processed window
1351  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1352  * Parameters:
1353  * @ctx must point to an previously initialized `nk_context` struct
1354  * @bounds points to a `nk_rect` struct with the new position and size of currently active window */
1355 NK_API void nk_window_set_bounds(struct nk_context*, struct nk_rect bounds);
1356 /* nk_window_set_position - updates position of the currently processed window
1357  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1358  * Parameters:
1359  * @ctx must point to an previously initialized `nk_context` struct
1360  * @pos points to a `nk_vec2` struct with the new position of currently active window */
1361 NK_API void nk_window_set_position(struct nk_context*, struct nk_vec2 pos);
1362 /* nk_window_set_size - updates size of the currently processed window
1363  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1364  * Parameters:
1365  * @ctx must point to an previously initialized `nk_context` struct
1366  * @bounds points to a `nk_vec2` struct with the new size of currently active window */
1367 NK_API void nk_window_set_size(struct nk_context*, struct nk_vec2);
1368 /* nk_window_set_focus - sets the window with given name as active
1369  * Parameters:
1370  * @ctx must point to an previously initialized `nk_context` struct
1371  * @name of the window to be set active */
1372 NK_API void nk_window_set_focus(struct nk_context*, const char *name);
1373 /* nk_window_close - closed a window and marks it for being freed at the end of the frame
1374  * Parameters:
1375  * @ctx must point to an previously initialized `nk_context` struct
1376  * @name of the window to be closed */
1377 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
1378 /* nk_window_collapse - updates collapse state of a window with given name
1379  * Parameters:
1380  * @ctx must point to an previously initialized `nk_context` struct
1381  * @name of the window to be either collapse or maximize */
1382 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1383 /* nk_window_collapse - updates collapse state of a window with given name if given condition is met
1384  * Parameters:
1385  * @ctx must point to an previously initialized `nk_context` struct
1386  * @name of the window to be either collapse or maximize
1387  * @state the window should be put into
1388  * @condition that has to be true to actually commit the collsage state change */
1389 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1390 /* nk_window_show - updates visibility state of a window with given name
1391  * Parameters:
1392  * @ctx must point to an previously initialized `nk_context` struct
1393  * @name of the window to be either collapse or maximize
1394  * @state with either visible or hidden to modify the window with */
1395 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1396 /* nk_window_show_if - updates visibility state of a window with given name if a given condition is met
1397  * Parameters:
1398  * @ctx must point to an previously initialized `nk_context` struct
1399  * @name of the window to be either collapse or maximize
1400  * @state with either visible or hidden to modify the window with
1401  * @condition that has to be true to actually commit the visible state change */
1402 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1403 /* =============================================================================
1404  *
1405  * LAYOUT
1406  *
1407  * ============================================================================= */
1408 /* Layouting in general describes placing widget inside a window with position and size.
1409  * While in this particular implementation there are five different APIs for layouting
1410  * each with different trade offs between control and ease of use.
1411  *
1412  * All layouting methodes in this library are based around the concept of a row.
1413  * A row has a height the window content grows by and a number of columns and each
1414  * layouting method specifies how each widget is placed inside the row.
1415  * After a row has been allocated by calling a layouting functions and then
1416  * filled with widgets will advance an internal pointer over the allocated row.
1417  *
1418  * To acually define a layout you just call the appropriate layouting function
1419  * and each subsequnetial widget call will place the widget as specified. Important
1420  * here is that if you define more widgets then columns defined inside the layout
1421  * functions it will allocate the next row without you having to make another layouting
1422  * call.
1423  *
1424  * Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API
1425  * is that you have to define the row height for each. However the row height
1426  * often depends on the height of the font. So I would recommend writing
1427  * a higher level layouting functions that just calls each function with default font height
1428  * plus some spacing between rows. The reason why this library does't support this
1429  * behavior by default is to grant more control.
1430  *
1431  * For actually more advanced UI I would even recommend using the `nk_layout_space_xxx`
1432  * layouting method in combination with a cassowary constraint solver (there are
1433  * some versions on github with permissive license model) to take over all control over widget
1434  * layouting yourself. However for quick and dirty layouting using all the other layouting
1435  * functions, especially if you don't change the font height, should be fine.
1436  *
1437  * Usage
1438  * -------------------
1439  * 1.) nk_layout_row_dynamic
1440  * The easiest layouting function is `nk_layout_row_dynamic`. It provides each
1441  * widgets with same horizontal space inside the row and dynamically grows
1442  * if the owning window grows in width. So the number of columns dictates
1443  * the size of each widget dynamically by formula:
1444  *
1445  * widget_width = (window_width - padding - spacing) * (1/colum_count)
1446  *
1447  * Just like all other layouting APIs if you define more widget than columns this
1448  * library will allocate a new row and keep all layouting parameters previously
1449  * defined.
1450  *
1451  * if (nk_begin_xxx(...) {
1452  * // first row with height: 30 composed of two widgets
1453  * nk_layout_row_dynamic(&ctx, 30, 2);
1454  * nk_widget(...);
1455  * nk_widget(...);
1456  *
1457  * // second row with same parameter as defined above
1458  * nk_widget(...);
1459  * nk_widget(...);
1460  * }
1461  * nk_end(...);
1462  *
1463  * 2.) nk_layout_row_static
1464  * Another easy layouting function is `nk_layout_row_static`. It provides each
1465  * widget with same horizontal pixel width inside the row and does not grow
1466  * if the owning window scales smaller or bigger.
1467  *
1468  * if (nk_begin_xxx(...) {
1469  * // first row with height: 30 composed of two widgets with width: 80
1470  * nk_layout_row_static(&ctx, 30, 80, 2);
1471  * nk_widget(...);
1472  * nk_widget(...);
1473  *
1474  * // second row with same parameter as defined above
1475  * nk_widget(...);
1476  * nk_widget(...);
1477  * }
1478  * nk_end(...);
1479  *
1480  * 3.) nk_layout_row_xxx
1481  * A little bit more advanced layouting API are functions `nk_layout_row_begin`,
1482  * `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly
1483  * specify each column pixel or window ratio in a row. It support either
1484  * directly setting per column pixel width or widget window ratio but not
1485  * both. Furthermore it is a immediate mode API so each value is directly
1486  * pushed before calling a widget. Therefore the layout is not automatically
1487  * repeating like the last two layouting functions.
1488  *
1489  * if (nk_begin_xxx(...) {
1490  * // first row with height: 25 composed of two widgets with width 60 and 40
1491  * nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
1492  * nk_layout_row_push(ctx, 60);
1493  * nk_widget(...);
1494  * nk_layout_row_push(ctx, 40);
1495  * nk_widget(...);
1496  * nk_layout_row_end(ctx);
1497  *
1498  * // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75
1499  * nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2);
1500  * nk_layout_row_push(ctx, 0.25f);
1501  * nk_widget(...);
1502  * nk_layout_row_push(ctx, 0.75f);
1503  * nk_widget(...);
1504  * nk_layout_row_end(ctx);
1505  * }
1506  * nk_end(...);
1507  *
1508  * 4.) nk_layout_row
1509  * The retain mode counterpart to API nk_layout_row_xxx is the single nk_layout_row
1510  * functions. Instead of pushing either pixel or window ratio for every widget
1511  * it allows to define it by array. The trade of for less control is that
1512  * `nk_layout_row` is automatically repeating. Otherwise the behavior is the
1513  * same.
1514  *
1515  * if (nk_begin_xxx(...) {
1516  * // two rows with height: 30 composed of two widgets with width 60 and 40
1517  * const float size[] = {60,40};
1518  * nk_layout_row(ctx, NK_STATIC, 30, 2, ratio);
1519  * nk_widget(...);
1520  * nk_widget(...);
1521  * nk_widget(...);
1522  * nk_widget(...);
1523  *
1524  * // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75
1525  * const float ratio[] = {0.25, 0.75};
1526  * nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
1527  * nk_widget(...);
1528  * nk_widget(...);
1529  * nk_widget(...);
1530  * nk_widget(...);
1531  * }
1532  * nk_end(...);
1533  *
1534  * 5.) nk_layout_row_template_xxx
1535  * The most complex and second most flexible API is a simplified flexbox version without
1536  * line wrapping and weights for dynamic widgets. It is an immediate mode API but
1537  * unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called
1538  * before calling the templated widgets.
1539  * The row template layout has three different per widget size specifier. The first
1540  * one is the static widget size specifier with fixed widget pixel width. They do
1541  * not grow if the row grows and will always stay the same. The second size
1542  * specifier is nk_layout_row_template_push_variable which defines a
1543  * minumum widget size but it also can grow if more space is available not taken
1544  * by other widgets. Finally there are dynamic widgets which are completly flexible
1545  * and unlike variable widgets can even shrink to zero if not enough space
1546  * is provided.
1547  *
1548  * if (nk_begin_xxx(...) {
1549  * // two rows with height: 30 composed of three widgets
1550  * nk_layout_row_template_begin(ctx, 30);
1551  * nk_layout_row_template_push_dynamic(ctx);
1552  * nk_layout_row_template_push_variable(ctx, 80);
1553  * nk_layout_row_template_push_static(ctx, 80);
1554  * nk_layout_row_template_end(ctx);
1555  *
1556  * nk_widget(...); // dynamic widget completly can go to zero
1557  * nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space
1558  * nk_widget(...); // static widget with fixed 80 pixel width
1559  * }
1560  * nk_end(...);
1561  *
1562  * 6.) nk_layout_space_xxx
1563  * Finally the most flexible API directly allows you to place widgets inside the
1564  * window. The space layout API is an immediate mode API which does not support
1565  * row auto repeat and directly sets position and size of a widget. Position
1566  * and size hereby can be either specified as ratio of alloated space or
1567  * allocated space local position and pixel size. Since this API is quite
1568  * powerfull there are a number of utility functions to get the available space
1569  * and convert between local allocated space and screen space.
1570  *
1571  * if (nk_begin_xxx(...) {
1572  * // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
1573  * nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX);
1574  * nk_layout_space_push(ctx, nk_rect(0,0,150,200));
1575  * nk_widget(...);
1576  * nk_layout_space_push(ctx, nk_rect(200,200,100,200));
1577  * nk_widget(...);
1578  * nk_layout_space_end(ctx);
1579  *
1580  * // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
1581  * nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX);
1582  * nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1));
1583  * nk_widget(...);
1584  * nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1));
1585  * nk_widget(...);
1586  * }
1587  * nk_end(...);
1588  *
1589  * Reference
1590  * -------------------
1591  * nk_layout_row_dynamic - current layout is divided into n same sized gowing columns
1592  * nk_layout_row_static - current layout is divided into n same fixed sized columns
1593  * nk_layout_row_begin - starts a new row with given height and number of columns
1594  * nk_layout_row_push - pushes another column with given size or window ratio
1595  * nk_layout_row_end - finished previously started row
1596  * nk_layout_row - specifies row columns in array as either window ratio or size
1597  *
1598  * nk_layout_row_template_begin
1599  * nk_layout_row_template_push_dynamic
1600  * nk_layout_row_template_push_variable
1601  * nk_layout_row_template_push_static
1602  * nk_layout_row_template_end
1603  *
1604  * nk_layout_space_begin
1605  * nk_layout_space_push
1606  * nk_layout_space_end
1607  *
1608  * nk_layout_space_bounds
1609  * nk_layout_space_to_screen
1610  * nk_layout_space_to_local
1611  * nk_layout_space_rect_to_screen
1612  * nk_layout_space_rect_to_local
1613  * nk_layout_ratio_from_pixel
1614  */
1615 /* nk_layout_row_dynamic - Sets current row layout to share horizontal space
1616  * between @cols number of widgets evenly. Once called all subsequent widget
1617  * calls greater than @cols will allocate a new row with same layout.
1618  * Parameters:
1619  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1620  * @height holds row height to allocate from panel for widget height
1621  * @cols number of widget inside row */
1622 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
1623 /* nk_layout_row_static - Sets current row layout to fill @cols number of widgets
1624  * in row with same @item_width horizontal size. Once called all subsequent widget
1625  * calls greater than @cols will allocate a new row with same layout.
1626  * Parameters:
1627  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1628  * @height holds row height to allocate from panel for widget height
1629  * @item_width holds width of each widget in row
1630  * @cols number of widget inside row */
1631 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
1632 /* nk_layout_row_begin - Starts a new dynamic or fixed row with given height and columns.
1633  * Parameters:
1634  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1635  * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1636  * @row_height holds width of each widget in row
1637  * @cols number of widget inside row */
1638 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
1639 /* nk_layout_row_push - Specifies either window ratio or width of a single column
1640  * Parameters:
1641  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin`
1642  * @value either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call */
1643 NK_API void nk_layout_row_push(struct nk_context*, float value);
1644 NK_API void nk_layout_row_end(struct nk_context*);
1645 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
1646 
1647 NK_API void nk_layout_row_template_begin(struct nk_context*, float height);
1649 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
1650 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width);
1652 
1653 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
1654 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect);
1655 NK_API void nk_layout_space_end(struct nk_context*);
1656 
1659 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
1662 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
1663 /* =============================================================================
1664  *
1665  * GROUP
1666  *
1667  * ============================================================================= */
1668 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags);
1669 NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char*, nk_flags);
1670 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll*, const char *title, nk_flags);
1672 NK_API void nk_group_end(struct nk_context*);
1673 /* =============================================================================
1674  *
1675  * LIST VIEW
1676  *
1677  * ============================================================================= */
1679 /* public: */
1680  int begin, end, count;
1681 /* private: */
1683  struct nk_context *ctx;
1684  nk_uint *scroll_pointer;
1685  nk_uint scroll_value;
1686 };
1687 NK_API int nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
1688 NK_API void nk_list_view_end(struct nk_list_view*);
1689 /* =============================================================================
1690  *
1691  * TREE
1692  *
1693  * ============================================================================= */
1694 #define nk_tree_push(ctx, type, title, state) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
1695 #define nk_tree_push_id(ctx, type, title, state, id) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
1696 NK_API int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
1697 #define nk_tree_image_push(ctx, type, img, title, state) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
1698 #define nk_tree_image_push_id(ctx, type, img, title, state, id) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
1699 NK_API int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
1700 NK_API void nk_tree_pop(struct nk_context*);
1701 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
1702 NK_API int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
1703 NK_API void nk_tree_state_pop(struct nk_context*);
1704 /* =============================================================================
1705  *
1706  * WIDGET
1707  *
1708  * ============================================================================= */
1710  NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
1711  NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
1712  NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
1713 };
1716  NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */
1717  NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */
1718  NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */
1719  NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */
1720  NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
1723 };
1724 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
1726 NK_API struct nk_rect nk_widget_bounds(struct nk_context*);
1728 NK_API struct nk_vec2 nk_widget_size(struct nk_context*);
1729 NK_API float nk_widget_width(struct nk_context*);
1730 NK_API float nk_widget_height(struct nk_context*);
1733 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down);
1734 NK_API void nk_spacing(struct nk_context*, int cols);
1735 /* =============================================================================
1736  *
1737  * TEXT
1738  *
1739  * ============================================================================= */
1747 };
1752 };
1753 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
1754 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
1755 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
1756 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
1757 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
1758 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
1759 NK_API void nk_label_wrap(struct nk_context*, const char*);
1760 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
1761 NK_API void nk_image(struct nk_context*, struct nk_image);
1762 #ifdef NK_INCLUDE_STANDARD_VARARGS
1763 NK_API void nk_labelf(struct nk_context*, nk_flags, const char*, ...);
1764 NK_API void nk_labelf_colored(struct nk_context*, nk_flags align, struct nk_color, const char*,...);
1765 NK_API void nk_labelf_wrap(struct nk_context*, const char*,...);
1766 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, const char*,...);
1767 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
1768 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
1769 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
1770 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
1771 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
1772 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
1773 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
1774 #endif
1775 /* =============================================================================
1776  *
1777  * BUTTON
1778  *
1779  * ============================================================================= */
1780 NK_API int nk_button_text(struct nk_context*, const char *title, int len);
1781 NK_API int nk_button_label(struct nk_context*, const char *title);
1782 NK_API int nk_button_color(struct nk_context*, struct nk_color);
1784 NK_API int nk_button_image(struct nk_context*, struct nk_image img);
1785 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
1786 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1787 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
1788 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
1789 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
1790 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
1791 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
1792 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
1793 NK_API int k_button_symbol_label_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, nk_flags text_alignment);
1794 NK_API int nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1795 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align);
1796 NK_API int nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment);
1797 NK_API int nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment);
1801 /* =============================================================================
1802  *
1803  * CHECKBOX
1804  *
1805  * ============================================================================= */
1806 NK_API int nk_check_label(struct nk_context*, const char*, int active);
1807 NK_API int nk_check_text(struct nk_context*, const char*, int,int active);
1808 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
1809 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
1810 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active);
1811 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active);
1812 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
1813 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
1814 /* =============================================================================
1815  *
1816  * RADIO BUTTON
1817  *
1818  * ============================================================================= */
1819 NK_API int nk_radio_label(struct nk_context*, const char*, int *active);
1820 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active);
1821 NK_API int nk_option_label(struct nk_context*, const char*, int active);
1822 NK_API int nk_option_text(struct nk_context*, const char*, int, int active);
1823 /* =============================================================================
1824  *
1825  * SELECTABLE
1826  *
1827  * ============================================================================= */
1828 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value);
1829 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value);
1830 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value);
1831 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value);
1832 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value);
1833 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value);
1834 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value);
1835 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value);
1836 /* =============================================================================
1837  *
1838  * SLIDER
1839  *
1840  * ============================================================================= */
1841 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
1842 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
1843 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
1844 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
1845 /* =============================================================================
1846  *
1847  * PROGRESSBAR
1848  *
1849  * ============================================================================= */
1850 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable);
1851 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable);
1852 
1853 /* =============================================================================
1854  *
1855  * COLOR PICKER
1856  *
1857  * ============================================================================= */
1858 NK_API struct nk_color nk_color_picker(struct nk_context*, struct nk_color, enum nk_color_format);
1859 NK_API int nk_color_pick(struct nk_context*, struct nk_color*, enum nk_color_format);
1860 /* =============================================================================
1861  *
1862  * PROPERTIES
1863  *
1864  * ============================================================================= */
1865 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
1866 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
1867 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
1868 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
1869 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
1870 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
1871 /* =============================================================================
1872  *
1873  * TEXT EDIT
1874  *
1875  * ============================================================================= */
1890 };
1896 };
1898  NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */
1899  NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */
1900  NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */
1901  NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
1902  NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */
1903 };
1904 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
1905 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter);
1906 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter);
1907 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags);
1908 NK_API void nk_edit_unfocus(struct nk_context*);
1909 /* =============================================================================
1910  *
1911  * CHART
1912  *
1913  * ============================================================================= */
1914 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
1915 NK_API int nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max);
1916 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
1917 NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value);
1918 NK_API nk_flags nk_chart_push(struct nk_context*, float);
1919 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
1920 NK_API void nk_chart_end(struct nk_context*);
1921 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
1922 NK_API void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userdata, float(*value_getter)(void* user, int index), int count, int offset);
1923 /* =============================================================================
1924  *
1925  * POPUP
1926  *
1927  * ============================================================================= */
1928 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
1929 NK_API void nk_popup_close(struct nk_context*);
1930 NK_API void nk_popup_end(struct nk_context*);
1931 /* =============================================================================
1932  *
1933  * COMBOBOX
1934  *
1935  * ============================================================================= */
1936 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
1937 NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size);
1938 NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size);
1939 NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size);
1940 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
1941 NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size);
1942 NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator,int *selected, int count, int item_height, struct nk_vec2 size);
1943 NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size);
1944 /* =============================================================================
1945  *
1946  * ABSTRACT COMBOBOX
1947  *
1948  * ============================================================================= */
1949 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
1950 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
1951 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
1952 NK_API int nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size);
1953 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
1954 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
1955 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size);
1956 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
1957 NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size);
1958 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
1959 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
1960 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
1961 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
1962 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
1963 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1964 NK_API void nk_combo_close(struct nk_context*);
1965 NK_API void nk_combo_end(struct nk_context*);
1966 /* =============================================================================
1967  *
1968  * CONTEXTUAL
1969  *
1970  * ============================================================================= */
1971 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
1972 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
1973 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
1974 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
1975 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
1976 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
1977 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1978 NK_API void nk_contextual_close(struct nk_context*);
1979 NK_API void nk_contextual_end(struct nk_context*);
1980 /* =============================================================================
1981  *
1982  * TOOLTIP
1983  *
1984  * ============================================================================= */
1985 NK_API void nk_tooltip(struct nk_context*, const char*);
1986 NK_API int nk_tooltip_begin(struct nk_context*, float width);
1987 NK_API void nk_tooltip_end(struct nk_context*);
1988 /* =============================================================================
1989  *
1990  * MENU
1991  *
1992  * ============================================================================= */
1993 NK_API void nk_menubar_begin(struct nk_context*);
1994 NK_API void nk_menubar_end(struct nk_context*);
1995 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
1996 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
1997 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
1998 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
1999 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
2000 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
2001 NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
2002 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
2003 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
2004 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
2005 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2006 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
2007 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2008 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2009 NK_API void nk_menu_close(struct nk_context*);
2010 NK_API void nk_menu_end(struct nk_context*);
2011 /* =============================================================================
2012  *
2013  * STYLE
2014  *
2015  * ============================================================================= */
2046 };
2056 };
2057 NK_API void nk_style_default(struct nk_context*);
2058 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
2059 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
2060 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
2062 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
2064 NK_API void nk_style_show_cursor(struct nk_context*);
2065 NK_API void nk_style_hide_cursor(struct nk_context*);
2066 
2067 NK_API int nk_style_push_font(struct nk_context*, struct nk_user_font*);
2068 NK_API int nk_style_push_float(struct nk_context*, float*, float);
2069 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
2071 NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags);
2072 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
2073 
2074 NK_API int nk_style_pop_font(struct nk_context*);
2075 NK_API int nk_style_pop_float(struct nk_context*);
2076 NK_API int nk_style_pop_vec2(struct nk_context*);
2078 NK_API int nk_style_pop_flags(struct nk_context*);
2079 NK_API int nk_style_pop_color(struct nk_context*);
2080 /* =============================================================================
2081  *
2082  * COLOR
2083  *
2084  * ============================================================================= */
2085 NK_API struct nk_color nk_rgb(int r, int g, int b);
2086 NK_API struct nk_color nk_rgb_iv(const int *rgb);
2087 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
2088 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
2089 NK_API struct nk_color nk_rgb_fv(const float *rgb);
2090 NK_API struct nk_color nk_rgb_hex(const char *rgb);
2091 
2092 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
2093 NK_API struct nk_color nk_rgba_u32(nk_uint);
2094 NK_API struct nk_color nk_rgba_iv(const int *rgba);
2095 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
2096 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
2097 NK_API struct nk_color nk_rgba_fv(const float *rgba);
2098 NK_API struct nk_color nk_rgba_hex(const char *rgb);
2099 
2100 NK_API struct nk_color nk_hsv(int h, int s, int v);
2101 NK_API struct nk_color nk_hsv_iv(const int *hsv);
2102 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
2103 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
2104 NK_API struct nk_color nk_hsv_fv(const float *hsv);
2105 
2106 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
2107 NK_API struct nk_color nk_hsva_iv(const int *hsva);
2108 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
2109 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
2110 NK_API struct nk_color nk_hsva_fv(const float *hsva);
2111 
2112 /* color (conversion nuklear --> user) */
2113 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
2114 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
2115 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
2116 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
2117 
2118 NK_API nk_uint nk_color_u32(struct nk_color);
2119 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
2120 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
2121 
2122 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
2123 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
2124 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
2125 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
2126 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
2127 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
2128 
2129 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
2130 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
2131 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
2132 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
2133 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
2134 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
2135 /* =============================================================================
2136  *
2137  * IMAGE
2138  *
2139  * ============================================================================= */
2140 NK_API nk_handle nk_handle_ptr(void*);
2141 NK_API nk_handle nk_handle_id(int);
2142 NK_API struct nk_image nk_image_handle(nk_handle);
2143 NK_API struct nk_image nk_image_ptr(void*);
2144 NK_API struct nk_image nk_image_id(int);
2145 NK_API int nk_image_is_subimage(const struct nk_image* img);
2146 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
2147 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
2148 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
2149 /* =============================================================================
2150  *
2151  * MATH
2152  *
2153  * ============================================================================= */
2154 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
2155 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
2156 
2157 NK_API struct nk_vec2 nk_vec2(float x, float y);
2158 NK_API struct nk_vec2 nk_vec2i(int x, int y);
2159 NK_API struct nk_vec2 nk_vec2v(const float *xy);
2160 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
2161 
2163 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
2164 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
2165 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
2166 NK_API struct nk_rect nk_rectv(const float *xywh);
2167 NK_API struct nk_rect nk_rectiv(const int *xywh);
2168 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
2169 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
2170 /* =============================================================================
2171  *
2172  * STRING
2173  *
2174  * ============================================================================= */
2175 NK_API int nk_strlen(const char *str);
2176 NK_API int nk_stricmp(const char *s1, const char *s2);
2177 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
2178 NK_API int nk_strtoi(const char *str, const char **endptr);
2179 NK_API float nk_strtof(const char *str, const char **endptr);
2180 NK_API double nk_strtod(const char *str, const char **endptr);
2181 NK_API int nk_strfilter(const char *text, const char *regexp);
2182 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
2183 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
2184 /* =============================================================================
2185  *
2186  * UTF-8
2187  *
2188  * ============================================================================= */
2189 NK_API int nk_utf_decode(const char*, nk_rune*, int);
2190 NK_API int nk_utf_encode(nk_rune, char*, int);
2191 NK_API int nk_utf_len(const char*, int byte_len);
2192 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
2193 /* ===============================================================
2194  *
2195  * FONT
2196  *
2197  * ===============================================================*/
2198 /* Font handling in this library was designed to be quite customizable and lets
2199  you decide what you want to use and what you want to provide. There are three
2200  different ways to use the font atlas. The first two will use your font
2201  handling scheme and only requires essential data to run nuklear. The next
2202  slightly more advanced features is font handling with vertex buffer output.
2203  Finally the most complex API wise is using nuklears font baking API.
2204 
2205  1.) Using your own implementation without vertex buffer output
2206  --------------------------------------------------------------
2207  So first up the easiest way to do font handling is by just providing a
2208  `nk_user_font` struct which only requires the height in pixel of the used
2209  font and a callback to calculate the width of a string. This way of handling
2210  fonts is best fitted for using the normal draw shape command API where you
2211  do all the text drawing yourself and the library does not require any kind
2212  of deeper knowledge about which font handling mechanism you use.
2213  IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
2214  over the complete life time! I know this sucks but it is currently the only
2215  way to switch between fonts.
2216 
2217  float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
2218  {
2219  your_font_type *type = handle.ptr;
2220  float text_width = ...;
2221  return text_width;
2222  }
2223 
2224  struct nk_user_font font;
2225  font.userdata.ptr = &your_font_class_or_struct;
2226  font.height = your_font_height;
2227  font.width = your_text_width_calculation;
2228 
2229  struct nk_context ctx;
2230  nk_init_default(&ctx, &font);
2231 
2232  2.) Using your own implementation with vertex buffer output
2233  --------------------------------------------------------------
2234  While the first approach works fine if you don't want to use the optional
2235  vertex buffer output it is not enough if you do. To get font handling working
2236  for these cases you have to provide two additional parameters inside the
2237  `nk_user_font`. First a texture atlas handle used to draw text as subimages
2238  of a bigger font atlas texture and a callback to query a character's glyph
2239  information (offset, size, ...). So it is still possible to provide your own
2240  font and use the vertex buffer output.
2241 
2242  float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
2243  {
2244  your_font_type *type = handle.ptr;
2245  float text_width = ...;
2246  return text_width;
2247  }
2248  void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
2249  {
2250  your_font_type *type = handle.ptr;
2251  glyph.width = ...;
2252  glyph.height = ...;
2253  glyph.xadvance = ...;
2254  glyph.uv[0].x = ...;
2255  glyph.uv[0].y = ...;
2256  glyph.uv[1].x = ...;
2257  glyph.uv[1].y = ...;
2258  glyph.offset.x = ...;
2259  glyph.offset.y = ...;
2260  }
2261 
2262  struct nk_user_font font;
2263  font.userdata.ptr = &your_font_class_or_struct;
2264  font.height = your_font_height;
2265  font.width = your_text_width_calculation;
2266  font.query = query_your_font_glyph;
2267  font.texture.id = your_font_texture;
2268 
2269  struct nk_context ctx;
2270  nk_init_default(&ctx, &font);
2271 
2272  3.) Nuklear font baker
2273  ------------------------------------
2274  The final approach if you do not have a font handling functionality or don't
2275  want to use it in this library is by using the optional font baker.
2276  The font baker API's can be used to create a font plus font atlas texture
2277  and can be used with or without the vertex buffer output.
2278 
2279  It still uses the `nk_user_font` struct and the two different approaches
2280  previously stated still work. The font baker is not located inside
2281  `nk_context` like all other systems since it can be understood as more of
2282  an extension to nuklear and does not really depend on any `nk_context` state.
2283 
2284  Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
2285  functions. If you don't care about memory just call the default version
2286  `nk_font_atlas_init_default` which will allocate all memory from the standard library.
2287  If you want to control memory allocation but you don't care if the allocated
2288  memory is temporary and therefore can be freed directly after the baking process
2289  is over or permanent you can call `nk_font_atlas_init`.
2290 
2291  After successfull intializing the font baker you can add Truetype(.ttf) fonts from
2292  different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
2293  functions. Adding font will permanently store each font, font config and ttf memory block(!)
2294  inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
2295  the font baker by for example adding additional fonts you can call
2296  `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
2297 
2298  As soon as you added all fonts you wanted you can now start the baking process
2299  for every selected glyphes to image by calling `nk_font_atlas_bake`.
2300  The baking process returns image memory, width and height which can be used to
2301  either create your own image object or upload it to any graphics library.
2302  No matter which case you finally have to call `nk_font_atlas_end` which
2303  will free all temporary memory including the font atlas image so make sure
2304  you created our texture beforehand. `nk_font_atlas_end` requires a handle
2305  to your font texture or object and optionally fills a `struct nk_draw_null_texture`
2306  which can be used for the optional vertex output. If you don't want it just
2307  set the argument to `NULL`.
2308 
2309  At this point you are done and if you don't want to reuse the font atlas you
2310  can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
2311  memory. Finally if you don't use the font atlas and any of it's fonts anymore
2312  you need to call `nk_font_atlas_clear` to free all memory still being used.
2313 
2314  struct nk_font_atlas atlas;
2315  nk_font_atlas_init_default(&atlas);
2316  nk_font_atlas_begin(&atlas);
2317  nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
2318  nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
2319  const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
2320  nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
2321 
2322  struct nk_context ctx;
2323  nk_init_default(&ctx, &font->handle);
2324  while (1) {
2325 
2326  }
2327  nk_font_atlas_clear(&atlas);
2328 
2329  The font baker API is probably the most complex API inside this library and
2330  I would suggest reading some of my examples `example/` to get a grip on how
2331  to use the font atlas. There are a number of details I left out. For example
2332  how to merge fonts, configure a font with `nk_font_config` to use other languages,
2333  use another texture coodinate format and a lot more:
2334 
2335  struct nk_font_config cfg = nk_font_config(font_pixel_height);
2336  cfg.merge_mode = nk_false or nk_true;
2337  cfg.range = nk_font_korean_glyph_ranges();
2338  cfg.coord_type = NK_COORD_PIXEL;
2339  nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
2340 
2341 */
2342 struct nk_user_font_glyph;
2343 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
2344 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
2345  struct nk_user_font_glyph *glyph,
2346  nk_rune codepoint, nk_rune next_codepoint);
2347 
2348 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
2349 struct nk_user_font_glyph {
2350  struct nk_vec2 uv[2];
2351  /* texture coordinates */
2352  struct nk_vec2 offset;
2353  /* offset between top left and glyph */
2354  float width, height;
2355  /* size of the glyph */
2356  float xadvance;
2357  /* offset to the next glyph */
2358 };
2359 #endif
2360 
2362  nk_handle userdata;
2363  /* user provided font handle */
2364  float height;
2365  /* max height of the font */
2367  /* font string width in pixel callback */
2368 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
2369  nk_query_font_glyph_f query;
2370  /* font glyph callback to query drawing info */
2371  nk_handle texture;
2372  /* texture handle to the used font atlas or texture */
2373 #endif
2374 };
2375 
2376 #ifdef NK_INCLUDE_FONT_BAKING
2377 enum nk_font_coord_type {
2378  NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
2379  NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
2380 };
2381 
2382 struct nk_baked_font {
2383  float height;
2384  /* height of the font */
2385  float ascent, descent;
2386  /* font glyphs ascent and descent */
2387  nk_rune glyph_offset;
2388  /* glyph array offset inside the font glyph baking output array */
2389  nk_rune glyph_count;
2390  /* number of glyphs of this font inside the glyph baking array output */
2391  const nk_rune *ranges;
2392  /* font codepoint ranges as pairs of (from/to) and 0 as last element */
2393 };
2394 
2395 struct nk_font_config {
2396  struct nk_font_config *next;
2397  /* NOTE: only used internally */
2398  void *ttf_blob;
2399  /* pointer to loaded TTF file memory block.
2400  * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
2401  nk_size ttf_size;
2402  /* size of the loaded TTF file memory block
2403  * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
2404 
2405  unsigned char ttf_data_owned_by_atlas;
2406  /* used inside font atlas: default to: 0*/
2407  unsigned char merge_mode;
2408  /* merges this font into the last font */
2409  unsigned char pixel_snap;
2410  /* align every character to pixel boundary (if true set oversample (1,1)) */
2411  unsigned char oversample_v, oversample_h;
2412  /* rasterize at hight quality for sub-pixel position */
2413  unsigned char padding[3];
2414 
2415  float size;
2416  /* baked pixel height of the font */
2417  enum nk_font_coord_type coord_type;
2418  /* texture coordinate format with either pixel or UV coordinates */
2419  struct nk_vec2 spacing;
2420  /* extra pixel spacing between glyphs */
2421  const nk_rune *range;
2422  /* list of unicode ranges (2 values per range, zero terminated) */
2423  struct nk_baked_font *font;
2424  /* font to setup in the baking process: NOTE: not needed for font atlas */
2425  nk_rune fallback_glyph;
2426  /* fallback glyph to use if a given rune is not found */
2427 };
2428 
2429 struct nk_font_glyph {
2430  nk_rune codepoint;
2431  float xadvance;
2432  float x0, y0, x1, y1, w, h;
2433  float u0, v0, u1, v1;
2434 };
2435 
2436 struct nk_font {
2437  struct nk_font *next;
2438  struct nk_user_font handle;
2439  struct nk_baked_font info;
2440  float scale;
2441  struct nk_font_glyph *glyphs;
2442  const struct nk_font_glyph *fallback;
2443  nk_rune fallback_codepoint;
2444  nk_handle texture;
2445  struct nk_font_config *config;
2446 };
2447 
2448 enum nk_font_atlas_format {
2449  NK_FONT_ATLAS_ALPHA8,
2450  NK_FONT_ATLAS_RGBA32
2451 };
2452 
2453 struct nk_font_atlas {
2454  void *pixel;
2455  int tex_width;
2456  int tex_height;
2457 
2458  struct nk_allocator permanent;
2459  struct nk_allocator temporary;
2460 
2461  struct nk_recti custom;
2462  struct nk_cursor cursors[NK_CURSOR_COUNT];
2463 
2464  int glyph_count;
2465  struct nk_font_glyph *glyphs;
2466  struct nk_font *default_font;
2467  struct nk_font *fonts;
2468  struct nk_font_config *config;
2469  int font_num;
2470 };
2471 
2472 /* some language glyph codepoint ranges */
2473 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
2474 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
2475 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
2476 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
2477 
2478 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2479 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
2480 #endif
2481 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
2482 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
2483 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
2484 NK_API struct nk_font_config nk_font_config(float pixel_height);
2485 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
2486 #ifdef NK_INCLUDE_DEFAULT_FONT
2487 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
2488 #endif
2489 NK_API struct nk_font* nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, nk_size size, float height, const struct nk_font_config *config);
2490 #ifdef NK_INCLUDE_STANDARD_IO
2491 NK_API struct nk_font* nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, float height, const struct nk_font_config*);
2492 #endif
2493 NK_API struct nk_font *nk_font_atlas_add_compressed(struct nk_font_atlas*, void *memory, nk_size size, float height, const struct nk_font_config*);
2494 NK_API struct nk_font* nk_font_atlas_add_compressed_base85(struct nk_font_atlas*, const char *data, float height, const struct nk_font_config *config);
2495 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
2496 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
2497 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
2498 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
2499 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
2500 
2501 #endif
2502 
2503 /* ==============================================================
2504  *
2505  * MEMORY BUFFER
2506  *
2507  * ===============================================================*/
2508 /* A basic (double)-buffer with linear allocation and resetting as only
2509  freeing policy. The buffer's main purpose is to control all memory management
2510  inside the GUI toolkit and still leave memory control as much as possible in
2511  the hand of the user while also making sure the library is easy to use if
2512  not as much control is needed.
2513  In general all memory inside this library can be provided from the user in
2514  three different ways.
2515 
2516  The first way and the one providing most control is by just passing a fixed
2517  size memory block. In this case all control lies in the hand of the user
2518  since he can exactly control where the memory comes from and how much memory
2519  the library should consume. Of course using the fixed size API removes the
2520  ability to automatically resize a buffer if not enough memory is provided so
2521  you have to take over the resizing. While being a fixed sized buffer sounds
2522  quite limiting, it is very effective in this library since the actual memory
2523  consumption is quite stable and has a fixed upper bound for a lot of cases.
2524 
2525  If you don't want to think about how much memory the library should allocate
2526  at all time or have a very dynamic UI with unpredictable memory consumption
2527  habits but still want control over memory allocation you can use the dynamic
2528  allocator based API. The allocator consists of two callbacks for allocating
2529  and freeing memory and optional userdata so you can plugin your own allocator.
2530 
2531  The final and easiest way can be used by defining
2532  NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
2533  allocation functions malloc and free and takes over complete control over
2534  memory in this library.
2535 */
2537  void *memory;
2538  unsigned int type;
2539  nk_size size;
2540  nk_size allocated;
2541  nk_size needed;
2542  nk_size calls;
2543 };
2544 
2548 };
2549 
2554 };
2555 
2557  int active;
2558  nk_size offset;
2559 };
2560 
2561 struct nk_memory {void *ptr;nk_size size;};
2562 struct nk_buffer {
2564  /* buffer marker to free a buffer to a certain offset */
2566  /* allocator callback for dynamic buffers */
2568  /* memory management type */
2570  /* memory and size of the current memory block */
2572  /* growing factor for dynamic memory management */
2573  nk_size allocated;
2574  /* total amount of memory allocated */
2575  nk_size needed;
2576  /* totally consumed memory given that enough memory is present */
2577  nk_size calls;
2578  /* number of allocation calls */
2579  nk_size size;
2580  /* current size of the buffer */
2581 };
2582 
2583 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2584 NK_API void nk_buffer_init_default(struct nk_buffer*);
2585 #endif
2586 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
2587 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
2588 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
2589 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
2590 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
2592 NK_API void nk_buffer_clear(struct nk_buffer*);
2593 NK_API void nk_buffer_free(struct nk_buffer*);
2594 NK_API void *nk_buffer_memory(struct nk_buffer*);
2595 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
2596 NK_API nk_size nk_buffer_total(struct nk_buffer*);
2597 
2598 /* ==============================================================
2599  *
2600  * STRING
2601  *
2602  * ===============================================================*/
2603 /* Basic string buffer which is only used in context with the text editor
2604  * to manage and manipulate dynamic or fixed size string content. This is _NOT_
2605  * the default string handling method. The only instance you should have any contact
2606  * with this API is if you interact with an `nk_text_edit` object inside one of the
2607  * copy and paste functions and even there only for more advanced cases. */
2608 struct nk_str {
2610  int len; /* in codepoints/runes/glyphs */
2611 };
2612 
2613 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2614 NK_API void nk_str_init_default(struct nk_str*);
2615 #endif
2616 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
2617 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
2618 NK_API void nk_str_clear(struct nk_str*);
2619 NK_API void nk_str_free(struct nk_str*);
2620 
2621 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
2622 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
2623 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
2624 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
2625 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
2626 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
2627 
2628 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
2629 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
2630 
2631 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
2632 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
2633 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
2634 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
2635 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
2636 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
2637 
2638 NK_API void nk_str_remove_chars(struct nk_str*, int len);
2639 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
2640 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
2641 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
2642 
2643 NK_API char *nk_str_at_char(struct nk_str*, int pos);
2644 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
2645 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
2646 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
2647 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
2648 
2649 NK_API char *nk_str_get(struct nk_str*);
2650 NK_API const char *nk_str_get_const(const struct nk_str*);
2651 NK_API int nk_str_len(struct nk_str*);
2652 NK_API int nk_str_len_char(struct nk_str*);
2653 
2654 /*===============================================================
2655  *
2656  * TEXT EDITOR
2657  *
2658  * ===============================================================*/
2659 /* Editing text in this library is handled by either `nk_edit_string` or
2660  * `nk_edit_buffer`. But like almost everything in this library there are multiple
2661  * ways of doing it and a balance between control and ease of use with memory
2662  * as well as functionality controlled by flags.
2663  *
2664  * This library generally allows three different levels of memory control:
2665  * First of is the most basic way of just providing a simple char array with
2666  * string length. This method is probably the easiest way of handling simple
2667  * user text input. Main upside is complete control over memory while the biggest
2668  * downside in comparsion with the other two approaches is missing undo/redo.
2669  *
2670  * For UIs that require undo/redo the second way was created. It is based on
2671  * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
2672  * This is mainly useful if you want something more like a text editor but don't want
2673  * to have a dynamically growing buffer.
2674  *
2675  * The final way is using a dynamically growing nk_text_edit struct, which
2676  * has both a default version if you don't care where memory comes from and an
2677  * allocator version if you do. While the text editor is quite powerful for its
2678  * complexity I would not recommend editing gigabytes of data with it.
2679  * It is rather designed for uses cases which make sense for a GUI library not for
2680  * an full blown text editor.
2681  */
2682 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
2683 #define NK_TEXTEDIT_UNDOSTATECOUNT 99
2684 #endif
2685 
2686 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
2687 #define NK_TEXTEDIT_UNDOCHARCOUNT 999
2688 #endif
2689 
2690 struct nk_text_edit;
2692  nk_handle userdata;
2695 };
2696 
2698  int where;
2702 };
2703 
2707  short undo_point;
2708  short redo_point;
2711 };
2712 
2716 };
2717 
2722 };
2723 
2726  struct nk_str string;
2729 
2730  int cursor;
2733  unsigned char mode;
2734  unsigned char cursor_at_end_of_line;
2735  unsigned char initialized;
2736  unsigned char has_preferred_x;
2737  unsigned char single_line;
2738  unsigned char active;
2739  unsigned char padding1;
2742 };
2743 
2744 /* filter function */
2745 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
2746 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
2747 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
2748 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
2749 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
2750 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
2751 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
2752 
2753 /* text editor */
2754 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2755 NK_API void nk_textedit_init_default(struct nk_text_edit*);
2756 #endif
2757 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size);
2758 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
2759 NK_API void nk_textedit_free(struct nk_text_edit*);
2760 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
2761 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
2764 NK_API int nk_textedit_cut(struct nk_text_edit*);
2765 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len);
2766 NK_API void nk_textedit_undo(struct nk_text_edit*);
2767 NK_API void nk_textedit_redo(struct nk_text_edit*);
2768 
2769 /* ===============================================================
2770  *
2771  * DRAWING
2772  *
2773  * ===============================================================*/
2774 /* This library was designed to be render backend agnostic so it does
2775  not draw anything to screen. Instead all drawn shapes, widgets
2776  are made of, are buffered into memory and make up a command queue.
2777  Each frame therefore fills the command buffer with draw commands
2778  that then need to be executed by the user and his own render backend.
2779  After that the command buffer needs to be cleared and a new frame can be
2780  started. It is probably important to note that the command buffer is the main
2781  drawing API and the optional vertex buffer API only takes this format and
2782  converts it into a hardware accessible format.
2783 
2784  To use the command queue to draw your own widgets you can access the
2785  command buffer of each window by calling `nk_window_get_canvas` after
2786  previously having called `nk_begin`:
2787 
2788  void draw_red_rectangle_widget(struct nk_context *ctx)
2789  {
2790  struct nk_command_buffer *canvas;
2791  struct nk_input *input = &ctx->input;
2792  canvas = nk_window_get_canvas(ctx);
2793 
2794  struct nk_rect space;
2795  enum nk_widget_layout_states state;
2796  state = nk_widget(&space, ctx);
2797  if (!state) return;
2798 
2799  if (state != NK_WIDGET_ROM)
2800  update_your_widget_by_user_input(...);
2801  nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
2802  }
2803 
2804  if (nk_begin(...)) {
2805  nk_layout_row_dynamic(ctx, 25, 1);
2806  draw_red_rectangle_widget(ctx);
2807  }
2808  nk_end(..)
2809 
2810  Important to know if you want to create your own widgets is the `nk_widget`
2811  call. It allocates space on the panel reserved for this widget to be used,
2812  but also returns the state of the widget space. If your widget is not seen and does
2813  not have to be updated it is '0' and you can just return. If it only has
2814  to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
2815  update and draw your widget. The reason for seperating is to only draw and
2816  update what is actually neccessary which is crucial for performance.
2817 */
2838 };
2839 
2840 /* command base and header of every command inside the buffer */
2841 struct nk_command {
2843  nk_size next;
2844 #ifdef NK_INCLUDE_COMMAND_USERDATA
2845  nk_handle userdata;
2846 #endif
2847 };
2848 
2851  short x, y;
2852  unsigned short w, h;
2853 };
2854 
2857  unsigned short line_thickness;
2858  struct nk_vec2i begin;
2859  struct nk_vec2i end;
2860  struct nk_color color;
2861 };
2862 
2865  unsigned short line_thickness;
2866  struct nk_vec2i begin;
2867  struct nk_vec2i end;
2868  struct nk_vec2i ctrl[2];
2869  struct nk_color color;
2870 };
2871 
2874  unsigned short rounding;
2875  unsigned short line_thickness;
2876  short x, y;
2877  unsigned short w, h;
2878  struct nk_color color;
2879 };
2880 
2883  unsigned short rounding;
2884  short x, y;
2885  unsigned short w, h;
2886  struct nk_color color;
2887 };
2888 
2891  short x, y;
2892  unsigned short w, h;
2893  struct nk_color left;
2894  struct nk_color top;
2896  struct nk_color right;
2897 };
2898 
2901  unsigned short line_thickness;
2902  struct nk_vec2i a;
2903  struct nk_vec2i b;
2904  struct nk_vec2i c;
2905  struct nk_color color;
2906 };
2907 
2910  struct nk_vec2i a;
2911  struct nk_vec2i b;
2912  struct nk_vec2i c;
2913  struct nk_color color;
2914 };
2915 
2918  short x, y;
2919  unsigned short line_thickness;
2920  unsigned short w, h;
2921  struct nk_color color;
2922 };
2923 
2926  short x, y;
2927  unsigned short w, h;
2928  struct nk_color color;
2929 };
2930 
2933  short cx, cy;
2934  unsigned short r;
2935  unsigned short line_thickness;
2936  float a[2];
2937  struct nk_color color;
2938 };
2939 
2942  short cx, cy;
2943  unsigned short r;
2944  float a[2];
2945  struct nk_color color;
2946 };
2947 
2950  struct nk_color color;
2951  unsigned short line_thickness;
2952  unsigned short point_count;
2953  struct nk_vec2i points[1];
2954 };
2955 
2958  struct nk_color color;
2959  unsigned short point_count;
2960  struct nk_vec2i points[1];
2961 };
2962 
2965  struct nk_color color;
2966  unsigned short line_thickness;
2967  unsigned short point_count;
2968  struct nk_vec2i points[1];
2969 };
2970 
2973  short x, y;
2974  unsigned short w, h;
2975  struct nk_image img;
2976  struct nk_color col;
2977 };
2978 
2979 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
2980  unsigned short w, unsigned short h, nk_handle callback_data);
2983  short x, y;
2984  unsigned short w, h;
2985  nk_handle callback_data;
2987 };
2988 
2991  const struct nk_user_font *font;
2994  short x, y;
2995  unsigned short w, h;
2996  float height;
2997  int length;
2998  char string[1];
2999 };
3000 
3004 };
3005 
3007  struct nk_buffer *base;
3008  struct nk_rect clip;
3010  nk_handle userdata;
3011  nk_size begin, end, last;
3012 };
3013 
3014 /* shape outlines */
3015 NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color);
3016 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
3017 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
3018 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
3019 NK_API void nk_stroke_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color);
3020 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
3021 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
3022 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
3023 
3024 /* filled shades */
3025 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
3026 NK_API void nk_fill_rect_multi_color(struct nk_command_buffer*, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
3027 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
3028 NK_API void nk_fill_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, struct nk_color);
3029 NK_API void nk_fill_triangle(struct nk_command_buffer*, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color);
3030 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
3031 
3032 /* misc */
3033 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
3034 NK_API void nk_draw_text(struct nk_command_buffer*, struct nk_rect, const char *text, int len, const struct nk_user_font*, struct nk_color, struct nk_color);
3035 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
3036 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr);
3037 
3038 /* ===============================================================
3039  *
3040  * INPUT
3041  *
3042  * ===============================================================*/
3044  int down;
3045  unsigned int clicked;
3047 };
3048 struct nk_mouse {
3050  struct nk_vec2 pos;
3051  struct nk_vec2 prev;
3052  struct nk_vec2 delta;
3054  unsigned char grab;
3055  unsigned char grabbed;
3056  unsigned char ungrab;
3057 };
3058 
3059 struct nk_key {
3060  int down;
3061  unsigned int clicked;
3062 };
3063 struct nk_keyboard {
3067 };
3068 
3069 struct nk_input {
3071  struct nk_mouse mouse;
3072 };
3073 
3074 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
3075 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
3076 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down);
3077 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
3078 NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down);
3079 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
3080 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
3081 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
3082 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
3083 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
3084 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
3085 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
3086 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
3087 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys);
3088 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys);
3089 
3090 /* ===============================================================
3091  *
3092  * DRAW LIST
3093  *
3094  * ===============================================================*/
3095 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
3096 /* The optional vertex buffer draw list provides a 2D drawing context
3097  with antialiasing functionality which takes basic filled or outlined shapes
3098  or a path and outputs vertexes, elements and draw commands.
3099  The actual draw list API is not required to be used directly while using this
3100  library since converting the default library draw command output is done by
3101  just calling `nk_convert` but I decided to still make this library accessible
3102  since it can be useful.
3103 
3104  The draw list is based on a path buffering and polygon and polyline
3105  rendering API which allows a lot of ways to draw 2D content to screen.
3106  In fact it is probably more powerful than needed but allows even more crazy
3107  things than this library provides by default.
3108 */
3109 typedef nk_ushort nk_draw_index;
3110 enum nk_draw_list_stroke {
3111  NK_STROKE_OPEN = nk_false,
3112  /* build up path has no connection back to the beginning */
3113  NK_STROKE_CLOSED = nk_true
3114  /* build up path has a connection back to the beginning */
3115 };
3116 
3117 enum nk_draw_vertex_layout_attribute {
3118  NK_VERTEX_POSITION,
3119  NK_VERTEX_COLOR,
3120  NK_VERTEX_TEXCOORD,
3121  NK_VERTEX_ATTRIBUTE_COUNT
3122 };
3123 
3124 enum nk_draw_vertex_layout_format {
3125  NK_FORMAT_SCHAR,
3126  NK_FORMAT_SSHORT,
3127  NK_FORMAT_SINT,
3128  NK_FORMAT_UCHAR,
3129  NK_FORMAT_USHORT,
3130  NK_FORMAT_UINT,
3131  NK_FORMAT_FLOAT,
3132  NK_FORMAT_DOUBLE,
3133 
3134 NK_FORMAT_COLOR_BEGIN,
3135  NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
3136  NK_FORMAT_R16G15B16,
3137  NK_FORMAT_R32G32B32,
3138 
3139  NK_FORMAT_R8G8B8A8,
3140  NK_FORMAT_R16G15B16A16,
3141  NK_FORMAT_R32G32B32A32,
3142  NK_FORMAT_R32G32B32A32_FLOAT,
3143  NK_FORMAT_R32G32B32A32_DOUBLE,
3144 
3145  NK_FORMAT_RGB32,
3146  NK_FORMAT_RGBA32,
3147 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
3148  NK_FORMAT_COUNT
3149 };
3150 
3151 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
3152 struct nk_draw_vertex_layout_element {
3153  enum nk_draw_vertex_layout_attribute attribute;
3154  enum nk_draw_vertex_layout_format format;
3155  nk_size offset;
3156 };
3157 
3158 struct nk_draw_command {
3159  unsigned int elem_count;
3160  /* number of elements in the current draw batch */
3161  struct nk_rect clip_rect;
3162  /* current screen clipping rectangle */
3163  nk_handle texture;
3164  /* current texture to set */
3165 #ifdef NK_INCLUDE_COMMAND_USERDATA
3166  nk_handle userdata;
3167 #endif
3168 };
3169 
3170 struct nk_draw_list {
3171  struct nk_rect clip_rect;
3172  struct nk_vec2 circle_vtx[12];
3173  struct nk_convert_config config;
3174 
3175  struct nk_buffer *buffer;
3176  struct nk_buffer *vertices;
3177  struct nk_buffer *elements;
3178 
3179  unsigned int element_count;
3180  unsigned int vertex_count;
3181  unsigned int cmd_count;
3182  nk_size cmd_offset;
3183 
3184  unsigned int path_count;
3185  unsigned int path_offset;
3186 
3187 #ifdef NK_INCLUDE_COMMAND_USERDATA
3188  nk_handle userdata;
3189 #endif
3190 };
3191 
3192 /* draw list */
3193 NK_API void nk_draw_list_init(struct nk_draw_list*);
3194 NK_API void nk_draw_list_setup(struct nk_draw_list*, const struct nk_convert_config*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements);
3195 NK_API void nk_draw_list_clear(struct nk_draw_list*);
3196 
3197 /* drawing */
3198 #define nk_draw_list_foreach(cmd, can, b) for((cmd)=nk__draw_list_begin(can, b); (cmd)!=0; (cmd)=nk__draw_list_next(cmd, b, can))
3199 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
3200 NK_API const struct nk_draw_command* nk__draw_list_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_draw_list*);
3201 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
3202 NK_API void nk_draw_list_clear(struct nk_draw_list *list);
3203 
3204 /* path */
3205 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
3206 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
3207 NK_API void nk_draw_list_path_arc_to_fast(struct nk_draw_list*, struct nk_vec2 center, float radius, int a_min, int a_max);
3208 NK_API void nk_draw_list_path_arc_to(struct nk_draw_list*, struct nk_vec2 center, float radius, float a_min, float a_max, unsigned int segments);
3209 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
3210 NK_API void nk_draw_list_path_curve_to(struct nk_draw_list*, struct nk_vec2 p2, struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments);
3211 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
3212 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
3213 
3214 /* stroke */
3215 NK_API void nk_draw_list_stroke_line(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_color, float thickness);
3216 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
3217 NK_API void nk_draw_list_stroke_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color, float thickness);
3218 NK_API void nk_draw_list_stroke_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color, unsigned int segs, float thickness);
3219 NK_API void nk_draw_list_stroke_curve(struct nk_draw_list*, struct nk_vec2 p0, struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, struct nk_color, unsigned int segments, float thickness);
3220 NK_API void nk_draw_list_stroke_poly_line(struct nk_draw_list*, const struct nk_vec2 *pnts, const unsigned int cnt, struct nk_color, enum nk_draw_list_stroke, float thickness, enum nk_anti_aliasing);
3221 
3222 /* fill */
3223 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
3224 NK_API void nk_draw_list_fill_rect_multi_color(struct nk_draw_list*, struct nk_rect rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
3225 NK_API void nk_draw_list_fill_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color);
3226 NK_API void nk_draw_list_fill_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color col, unsigned int segs);
3227 NK_API void nk_draw_list_fill_poly_convex(struct nk_draw_list*, const struct nk_vec2 *points, const unsigned int count, struct nk_color, enum nk_anti_aliasing);
3228 
3229 /* misc */
3230 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
3231 NK_API void nk_draw_list_add_text(struct nk_draw_list*, const struct nk_user_font*, struct nk_rect, const char *text, int len, float font_height, struct nk_color);
3232 #ifdef NK_INCLUDE_COMMAND_USERDATA
3233 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
3234 #endif
3235 
3236 #endif
3237 
3238 /* ===============================================================
3239  *
3240  * GUI
3241  *
3242  * ===============================================================*/
3246 };
3247 
3249  struct nk_image image;
3250  struct nk_color color;
3251 };
3252 
3256 };
3257 
3259  struct nk_color color;
3261 };
3262 
3264  /* background */
3269 
3270  /* text */
3275  nk_flags text_alignment;
3276 
3277  /* properties */
3278  float border;
3279  float rounding;
3283 
3284  /* optional user callbacks */
3285  nk_handle userdata;
3287  void(*draw_end)(struct nk_command_buffer*, nk_handle userdata);
3288 };
3289 
3291  /* background */
3296 
3297  /* cursor */
3300 
3301  /* text */
3306  nk_flags text_alignment;
3307 
3308  /* properties */
3311  float spacing;
3312  float border;
3313 
3314  /* optional user callbacks */
3315  nk_handle userdata;
3316  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3317  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3318 };
3319 
3321  /* background (inactive) */
3325 
3326  /* background (active) */
3330 
3331  /* text color (inactive) */
3335 
3336  /* text color (active) */
3341  nk_flags text_alignment;
3342 
3343  /* properties */
3344  float rounding;
3348 
3349  /* optional user callbacks */
3350  nk_handle userdata;
3351  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3352  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3353 };
3354 
3356  /* background */
3361 
3362  /* background bar */
3367 
3368  /* cursor */
3372 
3373  /* properties */
3374  float border;
3375  float rounding;
3376  float bar_height;
3380 
3381  /* optional buttons */
3387 
3388  /* optional user callbacks */
3389  nk_handle userdata;
3390  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3391  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3392 };
3393 
3395  /* background */
3400 
3401  /* cursor */
3406 
3407  /* properties */
3408  float rounding;
3409  float border;
3413 
3414  /* optional user callbacks */
3415  nk_handle userdata;
3416  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3417  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3418 };
3419 
3421  /* background */
3426 
3427  /* cursor */
3432 
3433  /* properties */
3434  float border;
3435  float rounding;
3439 
3440  /* optional buttons */
3446 
3447  /* optional user callbacks */
3448  nk_handle userdata;
3449  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3450  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3451 };
3452 
3454  /* background */
3460 
3461  /* cursor */
3466 
3467  /* text (unselected) */
3471 
3472  /* text (selected) */
3477 
3478  /* properties */
3479  float border;
3480  float rounding;
3485 };
3486 
3488  /* background */
3493 
3494  /* text */
3498 
3499  /* symbols */
3502 
3503  /* properties */
3504  float border;
3505  float rounding;
3507 
3511 
3512  /* optional user callbacks */
3513  nk_handle userdata;
3514  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3515  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3516 };
3517 
3519  /* colors */
3523  struct nk_color color;
3524 
3525  /* properties */
3526  float border;
3527  float rounding;
3529 };
3530 
3532  /* background */
3537 
3538  /* label */
3542 
3543  /* symbol */
3547 
3548  /* button */
3553 
3554  /* properties */
3555  float border;
3556  float rounding;
3560 };
3561 
3563  /* background */
3566  struct nk_color text;
3567 
3568  /* button */
3575 
3576  /* properties */
3577  float border;
3578  float rounding;
3579  float indent;
3582 };
3583 
3587 };
3589  /* background */
3593 
3594  /* button */
3600 
3601  /* title */
3605 
3606  /* properties */
3611 };
3612 
3617 
3626 
3627  float border;
3634 
3635  float rounding;
3639 
3647 };
3648 
3649 struct nk_style {
3650  const struct nk_user_font *font;
3652  const struct nk_cursor *cursor_active;
3655 
3673 };
3674 
3678 
3679 /*==============================================================
3680  * PANEL
3681  * =============================================================*/
3682 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
3683 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
3684 #endif
3685 #ifndef NK_CHART_MAX_SLOT
3686 #define NK_CHART_MAX_SLOT 4
3687 #endif
3688 
3697 };
3702 };
3703 
3706  struct nk_color color;
3708  float min, max, range;
3709  int count;
3710  struct nk_vec2 last;
3711  int index;
3712 };
3713 
3714 struct nk_chart {
3715  int slot;
3716  float x, y, w, h;
3718 };
3719 
3731 };
3734  int index;
3735  float height;
3736  int columns;
3737  const float *ratio;
3738  float item_width;
3741  float filled;
3742  struct nk_rect item;
3745 };
3746 
3748  nk_size begin;
3749  nk_size parent;
3750  nk_size last;
3751  nk_size end;
3752  int active;
3753 };
3754 
3756  float x, y, w, h;
3758 };
3759 
3760 struct nk_panel {
3762  nk_flags flags;
3763  struct nk_rect bounds;
3764  nk_uint *offset_x;
3765  nk_uint *offset_y;
3766  float at_x, at_y, max_x;
3769  float border;
3770  unsigned int has_scrolling;
3771  struct nk_rect clip;
3774  struct nk_chart chart;
3776  struct nk_panel *parent;
3777 };
3778 
3779 /*==============================================================
3780  * WINDOW
3781  * =============================================================*/
3782 #ifndef NK_WINDOW_MAX_NAME
3783 #define NK_WINDOW_MAX_NAME 64
3784 #endif
3785 
3786 struct nk_table;
3790  /* special window type growing up in height while being filled to a certain maximum height */
3792  /* sets window widgets into a read only mode and does not allow input changes */
3794  /* prevents all interaction caused by input to either window or widgets inside */
3796  /* Hides window and stops any window interaction and drawing */
3798  /* Directly closes and frees the window at the end of the frame */
3800  /* marks the window as minimized */
3802  /* Removes read only mode at the end of the window */
3803 };
3804 
3806  struct nk_window *win;
3809  nk_hash name;
3810  int active;
3811  unsigned combo_count;
3812  unsigned con_count, con_old;
3813  unsigned active_con;
3814  struct nk_rect header;
3815 };
3816 
3818  nk_hash name;
3819  unsigned int seq;
3820  unsigned int old;
3821  int active, prev;
3822  int cursor;
3824  int sel_end;
3826  unsigned char mode;
3827  unsigned char single_line;
3828 };
3829 
3831  int active, prev;
3833  int length;
3834  int cursor;
3837  nk_hash name;
3838  unsigned int seq;
3839  unsigned int old;
3840  int state;
3841 };
3842 
3843 struct nk_window {
3844  unsigned int seq;
3845  nk_hash name;
3847  nk_flags flags;
3848 
3849  struct nk_rect bounds;
3852  struct nk_panel *layout;
3854 
3855  /* persistent widget state */
3859  unsigned int scrolled;
3860 
3861  struct nk_table *tables;
3862  unsigned short table_count;
3863  unsigned short table_size;
3864 
3865  /* window list hooks */
3866  struct nk_window *next;
3867  struct nk_window *prev;
3869 };
3870 
3871 /*==============================================================
3872  * STACK
3873  * =============================================================*/
3874 /* The style modifier stack can be used to temporarily change a
3875  * property inside `nk_style`. For example if you want a special
3876  * red button you can temporarily push the old button color onto a stack
3877  * draw the button with a red color and then you just pop the old color
3878  * back from the stack:
3879  *
3880  * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
3881  * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
3882  * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
3883  * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
3884  *
3885  * nk_button(...);
3886  *
3887  * nk_style_pop_style_item(ctx);
3888  * nk_style_pop_style_item(ctx);
3889  * nk_style_pop_style_item(ctx);
3890  * nk_style_pop_vec2(ctx);
3891  *
3892  * Nuklear has a stack for style_items, float properties, vector properties,
3893  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
3894  * which can be changed at compile time.
3895  */
3896 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
3897 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
3898 #endif
3899 
3900 #ifndef NK_FONT_STACK_SIZE
3901 #define NK_FONT_STACK_SIZE 8
3902 #endif
3903 
3904 #ifndef NK_STYLE_ITEM_STACK_SIZE
3905 #define NK_STYLE_ITEM_STACK_SIZE 16
3906 #endif
3907 
3908 #ifndef NK_FLOAT_STACK_SIZE
3909 #define NK_FLOAT_STACK_SIZE 32
3910 #endif
3911 
3912 #ifndef NK_VECTOR_STACK_SIZE
3913 #define NK_VECTOR_STACK_SIZE 16
3914 #endif
3915 
3916 #ifndef NK_FLAGS_STACK_SIZE
3917 #define NK_FLAGS_STACK_SIZE 32
3918 #endif
3919 
3920 #ifndef NK_COLOR_STACK_SIZE
3921 #define NK_COLOR_STACK_SIZE 32
3922 #endif
3923 
3924 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
3925  struct nk_config_stack_##name##_element {\
3926  prefix##_##type *address;\
3927  prefix##_##type old_value;\
3928  }
3929 #define NK_CONFIG_STACK(type,size)\
3930  struct nk_config_stack_##type {\
3931  int head;\
3932  struct nk_config_stack_##type##_element elements[size];\
3933  }
3934 
3935 #define nk_float float
3936 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
3937 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
3938 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
3940 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
3941 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
3942 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
3943 
3951 
3953  struct nk_config_stack_style_item style_items;
3954  struct nk_config_stack_float floats;
3955  struct nk_config_stack_vec2 vectors;
3956  struct nk_config_stack_flags flags;
3957  struct nk_config_stack_color colors;
3958  struct nk_config_stack_user_font fonts;
3959  struct nk_config_stack_button_behavior button_behaviors;
3960 };
3961 
3962 /*==============================================================
3963  * CONTEXT
3964  * =============================================================*/
3965 #define NK_VALUE_PAGE_CAPACITY \
3966  ((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint)) / 2)
3967 
3968 struct nk_table {
3969  unsigned int seq;
3972  struct nk_table *next, *prev;
3973 };
3974 
3976  struct nk_table tbl;
3977  struct nk_panel pan;
3978  struct nk_window win;
3979 };
3980 
3985 };
3986 
3987 struct nk_page {
3988  unsigned int size;
3989  struct nk_page *next;
3991 };
3992 
3993 struct nk_pool {
3996  unsigned int page_count;
3997  struct nk_page *pages;
3999  unsigned capacity;
4000  nk_size size;
4001  nk_size cap;
4002 };
4003 
4004 struct nk_context {
4005 /* public: can be accessed freely */
4006  struct nk_input input;
4007  struct nk_style style;
4014 
4015 /* private:
4016  should only be accessed if you
4017  know what you are doing */
4018 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
4019  struct nk_draw_list draw_list;
4020 #endif
4021 #ifdef NK_INCLUDE_COMMAND_USERDATA
4022  nk_handle userdata;
4023 #endif
4024  /* text editor objects are quite big because of an internal
4025  * undo/redo stack. Therefore it does not make sense to have one for
4026  * each window for temporary use cases, so I only provide *one* instance
4027  * for all windows. This works because the content is cleared anyway */
4029  /* draw buffer used for overlay drawing operation like cursor */
4031 
4032  /* windows */
4033  int build;
4035  struct nk_pool pool;
4036  struct nk_window *begin;
4037  struct nk_window *end;
4041  unsigned int count;
4042  unsigned int seq;
4043 };
4044 
4045 /* ==============================================================
4046  * MATH
4047  * =============================================================== */
4048 #define NK_PI 3.141592654f
4049 #define NK_UTF_INVALID 0xFFFD
4050 #define NK_MAX_FLOAT_PRECISION 2
4051 
4052 #define NK_UNUSED(x) ((void)(x))
4053 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
4054 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
4055 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
4056 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
4057 #define NK_INBOX(px, py, x, y, w, h)\
4058  (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
4059 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
4060  (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))
4061 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
4062  (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
4063 
4064 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
4065 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
4066 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
4067 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
4068 
4069 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
4070 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
4071 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
4072 
4073 /* ==============================================================
4074  * ALIGNMENT
4075  * =============================================================== */
4076 /* Pointer to Integer type conversion for pointer alignment */
4077 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
4078 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
4079 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
4080 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
4081 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
4082 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
4083 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
4084 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
4085 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
4086 #else /* generates warning but works */
4087 # define NK_UINT_TO_PTR(x) ((void*)(x))
4088 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
4089 #endif
4090 
4091 #define NK_ALIGN_PTR(x, mask)\
4092  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
4093 #define NK_ALIGN_PTR_BACK(x, mask)\
4094  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
4095 
4096 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
4097 #define NK_CONTAINER_OF(ptr,type,member)\
4098  (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
4099 
4100 #ifdef __cplusplus
4101 }
4102 #endif
4103 
4104 #ifdef __cplusplus
4105 template<typename T> struct nk_alignof;
4106 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
4107 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
4108 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
4109  diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
4110 #define NK_ALIGNOF(t) (nk_alignof<t>::value);
4111 #elif defined(_MSC_VER)
4112 #define NK_ALIGNOF(t) (__alignof(t))
4113 #else
4114 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
4115 #endif
4116 
4117 #endif /* NK_H_ */
4118 /*
4119  * ==============================================================
4120  *
4121  * IMPLEMENTATION
4122  *
4123  * ===============================================================
4124  */
4125 #ifdef NK_IMPLEMENTATION
4126 
4127 #ifndef NK_POOL_DEFAULT_CAPACITY
4128 #define NK_POOL_DEFAULT_CAPACITY 16
4129 #endif
4130 
4131 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
4132 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
4133 #endif
4134 
4135 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
4136 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
4137 #endif
4138 
4139 /* standard library headers */
4140 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4141 #include <stdlib.h> /* malloc, free */
4142 #endif
4143 #ifdef NK_INCLUDE_STANDARD_IO
4144 #include <stdio.h> /* fopen, fclose,... */
4145 #endif
4146 #ifdef NK_INCLUDE_STANDARD_VARARGS
4147 #include <stdarg.h> /* valist, va_start, va_end, ... */
4148 #endif
4149 #ifndef NK_ASSERT
4150 #include <assert.h>
4151 #define NK_ASSERT(expr) assert(expr)
4152 #endif
4153 
4154 #ifndef NK_MEMSET
4155 #define NK_MEMSET nk_memset
4156 #endif
4157 #ifndef NK_MEMCPY
4158 #define NK_MEMCPY nk_memcopy
4159 #endif
4160 #ifndef NK_SQRT
4161 #define NK_SQRT nk_sqrt
4162 #endif
4163 #ifndef NK_SIN
4164 #define NK_SIN nk_sin
4165 #endif
4166 #ifndef NK_COS
4167 #define NK_COS nk_cos
4168 #endif
4169 #ifndef NK_STRTOD
4170 #define NK_STRTOD nk_strtod
4171 #endif
4172 #ifndef NK_DTOA
4173 #define NK_DTOA nk_dtoa
4174 #endif
4175 
4176 #define NK_DEFAULT (-1)
4177 
4178 #ifndef NK_VSNPRINTF
4179 /* If your compiler does support `vsnprintf` I would highly recommend
4180  * defining this to vsnprintf instead since `vsprintf` is basically
4181  * unbelievable unsafe and should *NEVER* be used. But I have to support
4182  * it since C89 only provides this unsafe version. */
4183  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
4184  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
4185  (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
4186  (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
4187  defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
4188  #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
4189  #else
4190  #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
4191  #endif
4192 #endif
4193 
4194 #define NK_SCHAR_MIN (-127)
4195 #define NK_SCHAR_MAX 127
4196 #define NK_UCHAR_MIN 0
4197 #define NK_UCHAR_MAX 256
4198 #define NK_SSHORT_MIN (-32767)
4199 #define NK_SSHORT_MAX 32767
4200 #define NK_USHORT_MIN 0
4201 #define NK_USHORT_MAX 65535
4202 #define NK_SINT_MIN (-2147483647)
4203 #define NK_SINT_MAX 2147483647
4204 #define NK_UINT_MIN 0
4205 #define NK_UINT_MAX 4294967295u
4206 
4207 /* Make sure correct type size:
4208  * This will fire with a negative subscript error if the type sizes
4209  * are set incorrectly by the compiler, and compile out if not */
4210 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
4211 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
4212 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
4213 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
4214 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
4215 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
4216 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
4217 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
4218 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
4219 
4220 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
4221 #define NK_FLOAT_PRECISION 0.00000000000001
4222 
4223 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
4224 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
4225 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
4226 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
4227 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
4228 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
4229 
4230 /*
4231  * ==============================================================
4232  *
4233  * MATH
4234  *
4235  * ===============================================================
4236  */
4237 /* Since nuklear is supposed to work on all systems providing floating point
4238  math without any dependencies I also had to implement my own math functions
4239  for sqrt, sin and cos. Since the actual highly accurate implementations for
4240  the standard library functions are quite complex and I do not need high
4241  precision for my use cases I use approximations.
4242 
4243  Sqrt
4244  ----
4245  For square root nuklear uses the famous fast inverse square root:
4246  https://en.wikipedia.org/wiki/Fast_inverse_square_root with
4247  slightly tweaked magic constant. While on todays hardware it is
4248  probably not faster it is still fast and accurate enough for
4249  nuklear's use cases. IMPORTANT: this requires float format IEEE 754
4250 
4251  Sine/Cosine
4252  -----------
4253  All constants inside both function are generated Remez's minimax
4254  approximations for value range 0...2*PI. The reason why I decided to
4255  approximate exactly that range is that nuklear only needs sine and
4256  cosine to generate circles which only requires that exact range.
4257  In addition I used Remez instead of Taylor for additional precision:
4258  www.lolengine.net/blog/2011/12/21/better-function-approximatations.
4259 
4260  The tool I used to generate constants for both sine and cosine
4261  (it can actually approximate a lot more functions) can be
4262  found here: www.lolengine.net/wiki/oss/lolremez
4263 */
4264 NK_INTERN float
4265 nk_inv_sqrt(float number)
4266 {
4267  float x2;
4268  const float threehalfs = 1.5f;
4269  union {nk_uint i; float f;} conv = {0};
4270  conv.f = number;
4271  x2 = number * 0.5f;
4272  conv.i = 0x5f375A84 - (conv.i >> 1);
4273  conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
4274  return conv.f;
4275 }
4276 
4277 NK_INTERN float
4278 nk_sqrt(float x)
4279 {
4280  return x * nk_inv_sqrt(x);
4281 }
4282 
4283 NK_INTERN float
4284 nk_sin(float x)
4285 {
4286  NK_STORAGE const float a0 = +1.91059300966915117e-31f;
4287  NK_STORAGE const float a1 = +1.00086760103908896f;
4288  NK_STORAGE const float a2 = -1.21276126894734565e-2f;
4289  NK_STORAGE const float a3 = -1.38078780785773762e-1f;
4290  NK_STORAGE const float a4 = -2.67353392911981221e-2f;
4291  NK_STORAGE const float a5 = +2.08026600266304389e-2f;
4292  NK_STORAGE const float a6 = -3.03996055049204407e-3f;
4293  NK_STORAGE const float a7 = +1.38235642404333740e-4f;
4294  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
4295 }
4296 
4297 NK_INTERN float
4298 nk_cos(float x)
4299 {
4300  NK_STORAGE const float a0 = +1.00238601909309722f;
4301  NK_STORAGE const float a1 = -3.81919947353040024e-2f;
4302  NK_STORAGE const float a2 = -3.94382342128062756e-1f;
4303  NK_STORAGE const float a3 = -1.18134036025221444e-1f;
4304  NK_STORAGE const float a4 = +1.07123798512170878e-1f;
4305  NK_STORAGE const float a5 = -1.86637164165180873e-2f;
4306  NK_STORAGE const float a6 = +9.90140908664079833e-4f;
4307  NK_STORAGE const float a7 = -5.23022132118824778e-14f;
4308  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
4309 }
4310 
4311 NK_INTERN nk_uint
4312 nk_round_up_pow2(nk_uint v)
4313 {
4314  v--;
4315  v |= v >> 1;
4316  v |= v >> 2;
4317  v |= v >> 4;
4318  v |= v >> 8;
4319  v |= v >> 16;
4320  v++;
4321  return v;
4322 }
4323 
4324 NK_API struct nk_rect
4326 {
4327  return nk_null_rect;
4328 }
4329 
4330 NK_API struct nk_rect
4331 nk_rect(float x, float y, float w, float h)
4332 {
4333  struct nk_rect r;
4334  r.x = x; r.y = y;
4335  r.w = w; r.h = h;
4336  return r;
4337 }
4338 
4339 NK_API struct nk_rect
4340 nk_recti(int x, int y, int w, int h)
4341 {
4342  struct nk_rect r;
4343  r.x = (float)x;
4344  r.y = (float)y;
4345  r.w = (float)w;
4346  r.h = (float)h;
4347  return r;
4348 }
4349 
4350 NK_API struct nk_rect
4351 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
4352 {
4353  return nk_rect(pos.x, pos.y, size.x, size.y);
4354 }
4355 
4356 NK_API struct nk_rect
4357 nk_rectv(const float *r)
4358 {
4359  return nk_rect(r[0], r[1], r[2], r[3]);
4360 }
4361 
4362 NK_API struct nk_rect
4363 nk_rectiv(const int *r)
4364 {
4365  return nk_recti(r[0], r[1], r[2], r[3]);
4366 }
4367 
4368 NK_API struct nk_vec2
4369 nk_rect_pos(struct nk_rect r)
4370 {
4371  struct nk_vec2 ret;
4372  ret.x = r.x; ret.y = r.y;
4373  return ret;
4374 }
4375 
4376 NK_API struct nk_vec2
4377 nk_rect_size(struct nk_rect r)
4378 {
4379  struct nk_vec2 ret;
4380  ret.x = r.w; ret.y = r.h;
4381  return ret;
4382 }
4383 
4384 NK_INTERN struct nk_rect
4385 nk_shrink_rect(struct nk_rect r, float amount)
4386 {
4387  struct nk_rect res;
4388  r.w = NK_MAX(r.w, 2 * amount);
4389  r.h = NK_MAX(r.h, 2 * amount);
4390  res.x = r.x + amount;
4391  res.y = r.y + amount;
4392  res.w = r.w - 2 * amount;
4393  res.h = r.h - 2 * amount;
4394  return res;
4395 }
4396 
4397 NK_INTERN struct nk_rect
4398 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
4399 {
4400  r.w = NK_MAX(r.w, 2 * pad.x);
4401  r.h = NK_MAX(r.h, 2 * pad.y);
4402  r.x += pad.x; r.y += pad.y;
4403  r.w -= 2 * pad.x;
4404  r.h -= 2 * pad.y;
4405  return r;
4406 }
4407 
4408 NK_API struct nk_vec2
4409 nk_vec2(float x, float y)
4410 {
4411  struct nk_vec2 ret;
4412  ret.x = x; ret.y = y;
4413  return ret;
4414 }
4415 
4416 NK_API struct nk_vec2
4417 nk_vec2i(int x, int y)
4418 {
4419  struct nk_vec2 ret;
4420  ret.x = (float)x;
4421  ret.y = (float)y;
4422  return ret;
4423 }
4424 
4425 NK_API struct nk_vec2
4426 nk_vec2v(const float *v)
4427 {
4428  return nk_vec2(v[0], v[1]);
4429 }
4430 
4431 NK_API struct nk_vec2
4432 nk_vec2iv(const int *v)
4433 {
4434  return nk_vec2i(v[0], v[1]);
4435 }
4436 
4437 /*
4438  * ==============================================================
4439  *
4440  * UTIL
4441  *
4442  * ===============================================================
4443  */
4444 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
4445 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
4446 NK_INTERN int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
4447 NK_INTERN int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
4448 NK_INTERN int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
4449 NK_INTERN int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
4450 
4451 NK_INTERN void*
4452 nk_memcopy(void *dst0, const void *src0, nk_size length)
4453 {
4454  nk_ptr t;
4455  char *dst = (char*)dst0;
4456  const char *src = (const char*)src0;
4457  if (length == 0 || dst == src)
4458  goto done;
4459 
4460  #define nk_word int
4461  #define nk_wsize sizeof(nk_word)
4462  #define nk_wmask (nk_wsize-1)
4463  #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
4464  #define NK_TLOOP1(s) do { s; } while (--t)
4465 
4466  if (dst < src) {
4467  t = (nk_ptr)src; /* only need low bits */
4468  if ((t | (nk_ptr)dst) & nk_wmask) {
4469  if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
4470  t = length;
4471  else
4472  t = nk_wsize - (t & nk_wmask);
4473  length -= t;
4474  NK_TLOOP1(*dst++ = *src++);
4475  }
4476  t = length / nk_wsize;
4477  NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
4478  src += nk_wsize; dst += nk_wsize);
4479  t = length & nk_wmask;
4480  NK_TLOOP(*dst++ = *src++);
4481  } else {
4482  src += length;
4483  dst += length;
4484  t = (nk_ptr)src;
4485  if ((t | (nk_ptr)dst) & nk_wmask) {
4486  if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
4487  t = length;
4488  else
4489  t &= nk_wmask;
4490  length -= t;
4491  NK_TLOOP1(*--dst = *--src);
4492  }
4493  t = length / nk_wsize;
4494  NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
4495  *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
4496  t = length & nk_wmask;
4497  NK_TLOOP(*--dst = *--src);
4498  }
4499  #undef nk_word
4500  #undef nk_wsize
4501  #undef nk_wmask
4502  #undef NK_TLOOP
4503  #undef NK_TLOOP1
4504 done:
4505  return (dst0);
4506 }
4507 
4508 NK_INTERN void
4509 nk_memset(void *ptr, int c0, nk_size size)
4510 {
4511  #define nk_word unsigned
4512  #define nk_wsize sizeof(nk_word)
4513  #define nk_wmask (nk_wsize - 1)
4514  nk_byte *dst = (nk_byte*)ptr;
4515  unsigned c = 0;
4516  nk_size t = 0;
4517 
4518  if ((c = (nk_byte)c0) != 0) {
4519  c = (c << 8) | c; /* at least 16-bits */
4520  if (sizeof(unsigned int) > 2)
4521  c = (c << 16) | c; /* at least 32-bits*/
4522  }
4523 
4524  /* too small of a word count */
4525  dst = (nk_byte*)ptr;
4526  if (size < 3 * nk_wsize) {
4527  while (size--) *dst++ = (nk_byte)c0;
4528  return;
4529  }
4530 
4531  /* align destination */
4532  if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
4533  t = nk_wsize -t;
4534  size -= t;
4535  do {
4536  *dst++ = (nk_byte)c0;
4537  } while (--t != 0);
4538  }
4539 
4540  /* fill word */
4541  t = size / nk_wsize;
4542  do {
4543  *(nk_word*)((void*)dst) = c;
4544  dst += nk_wsize;
4545  } while (--t != 0);
4546 
4547  /* fill trailing bytes */
4548  t = (size & nk_wmask);
4549  if (t != 0) {
4550  do {
4551  *dst++ = (nk_byte)c0;
4552  } while (--t != 0);
4553  }
4554 
4555  #undef nk_word
4556  #undef nk_wsize
4557  #undef nk_wmask
4558 }
4559 
4560 NK_INTERN void
4561 nk_zero(void *ptr, nk_size size)
4562 {
4563  NK_ASSERT(ptr);
4564  NK_MEMSET(ptr, 0, size);
4565 }
4566 
4567 NK_API int
4568 nk_strlen(const char *str)
4569 {
4570  int siz = 0;
4571  NK_ASSERT(str);
4572  while (str && *str++ != '\0') siz++;
4573  return siz;
4574 }
4575 
4576 NK_API int
4577 nk_strtoi(const char *str, const char **endptr)
4578 {
4579  int neg = 1;
4580  const char *p = str;
4581  int value = 0;
4582 
4583  NK_ASSERT(str);
4584  if (!str) return 0;
4585 
4586  /* skip whitespace */
4587  while (*p == ' ') p++;
4588  if (*p == '-') {
4589  neg = -1;
4590  p++;
4591  }
4592  while (*p && *p >= '0' && *p <= '9') {
4593  value = value * 10 + (int) (*p - '0');
4594  p++;
4595  }
4596  if (endptr)
4597  *endptr = p;
4598  return neg*value;
4599 }
4600 
4601 NK_API double
4602 nk_strtod(const char *str, const char **endptr)
4603 {
4604  double m;
4605  double neg = 1.0;
4606  const char *p = str;
4607  double value = 0;
4608  double number = 0;
4609 
4610  NK_ASSERT(str);
4611  if (!str) return 0;
4612 
4613  /* skip whitespace */
4614  while (*p == ' ') p++;
4615  if (*p == '-') {
4616  neg = -1.0;
4617  p++;
4618  }
4619 
4620  while (*p && *p != '.' && *p != 'e') {
4621  value = value * 10.0 + (double) (*p - '0');
4622  p++;
4623  }
4624 
4625  if (*p == '.') {
4626  p++;
4627  for(m = 0.1; *p && *p != 'e'; p++ ) {
4628  value = value + (double) (*p - '0') * m;
4629  m *= 0.1;
4630  }
4631  }
4632  if (*p == 'e') {
4633  int i, pow, div;
4634  p++;
4635  if (*p == '-') {
4636  div = nk_true;
4637  p++;
4638  } else if (*p == '+') {
4639  div = nk_false;
4640  p++;
4641  } else div = nk_false;
4642 
4643  for (pow = 0; *p; p++)
4644  pow = pow * 10 + (int) (*p - '0');
4645 
4646  for (m = 1.0, i = 0; i < pow; i++)
4647  m *= 10.0;
4648 
4649  if (div)
4650  value /= m;
4651  else value *= m;
4652  }
4653  number = value * neg;
4654  if (endptr)
4655  *endptr = p;
4656  return number;
4657 }
4658 
4659 NK_API float
4660 nk_strtof(const char *str, const char **endptr)
4661 {
4662  float float_value;
4663  double double_value;
4664  double_value = NK_STRTOD(str, endptr);
4665  float_value = (float)double_value;
4666  return float_value;
4667 }
4668 
4669 NK_API int
4670 nk_stricmp(const char *s1, const char *s2)
4671 {
4672  nk_int c1,c2,d;
4673  do {
4674  c1 = *s1++;
4675  c2 = *s2++;
4676  d = c1 - c2;
4677  while (d) {
4678  if (c1 <= 'Z' && c1 >= 'A') {
4679  d += ('a' - 'A');
4680  if (!d) break;
4681  }
4682  if (c2 <= 'Z' && c2 >= 'A') {
4683  d -= ('a' - 'A');
4684  if (!d) break;
4685  }
4686  return ((d >= 0) << 1) - 1;
4687  }
4688  } while (c1);
4689  return 0;
4690 }
4691 
4692 NK_API int
4693 nk_stricmpn(const char *s1, const char *s2, int n)
4694 {
4695  int c1,c2,d;
4696  NK_ASSERT(n >= 0);
4697  do {
4698  c1 = *s1++;
4699  c2 = *s2++;
4700  if (!n--) return 0;
4701 
4702  d = c1 - c2;
4703  while (d) {
4704  if (c1 <= 'Z' && c1 >= 'A') {
4705  d += ('a' - 'A');
4706  if (!d) break;
4707  }
4708  if (c2 <= 'Z' && c2 >= 'A') {
4709  d -= ('a' - 'A');
4710  if (!d) break;
4711  }
4712  return ((d >= 0) << 1) - 1;
4713  }
4714  } while (c1);
4715  return 0;
4716 }
4717 
4718 NK_INTERN int
4719 nk_str_match_here(const char *regexp, const char *text)
4720 {
4721  if (regexp[0] == '\0')
4722  return 1;
4723  if (regexp[1] == '*')
4724  return nk_str_match_star(regexp[0], regexp+2, text);
4725  if (regexp[0] == '$' && regexp[1] == '\0')
4726  return *text == '\0';
4727  if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
4728  return nk_str_match_here(regexp+1, text+1);
4729  return 0;
4730 }
4731 
4732 NK_INTERN int
4733 nk_str_match_star(int c, const char *regexp, const char *text)
4734 {
4735  do {/* a '* matches zero or more instances */
4736  if (nk_str_match_here(regexp, text))
4737  return 1;
4738  } while (*text != '\0' && (*text++ == c || c == '.'));
4739  return 0;
4740 }
4741 
4742 NK_API int
4743 nk_strfilter(const char *text, const char *regexp)
4744 {
4745  /*
4746  c matches any literal character c
4747  . matches any single character
4748  ^ matches the beginning of the input string
4749  $ matches the end of the input string
4750  * matches zero or more occurrences of the previous character*/
4751  if (regexp[0] == '^')
4752  return nk_str_match_here(regexp+1, text);
4753  do { /* must look even if string is empty */
4754  if (nk_str_match_here(regexp, text))
4755  return 1;
4756  } while (*text++ != '\0');
4757  return 0;
4758 }
4759 
4760 NK_API int
4761 nk_strmatch_fuzzy_text(const char *str, int str_len,
4762  const char *pattern, int *out_score)
4763 {
4764  /* Returns true if each character in pattern is found sequentially within str
4765  * if found then outScore is also set. Score value has no intrinsic meaning.
4766  * Range varies with pattern. Can only compare scores with same search pattern. */
4767 
4768  /* ------- scores --------- */
4769  /* bonus for adjacent matches */
4770  #define NK_ADJACENCY_BONUS 5
4771  /* bonus if match occurs after a separator */
4772  #define NK_SEPARATOR_BONUS 10
4773  /* bonus if match is uppercase and prev is lower */
4774  #define NK_CAMEL_BONUS 10
4775  /* penalty applied for every letter in str before the first match */
4776  #define NK_LEADING_LETTER_PENALTY (-3)
4777  /* maximum penalty for leading letters */
4778  #define NK_MAX_LEADING_LETTER_PENALTY (-9)
4779  /* penalty for every letter that doesn't matter */
4780  #define NK_UNMATCHED_LETTER_PENALTY (-1)
4781 
4782  /* loop variables */
4783  int score = 0;
4784  char const * pattern_iter = pattern;
4785  int str_iter = 0;
4786  int prev_matched = nk_false;
4787  int prev_lower = nk_false;
4788  /* true so if first letter match gets separator bonus*/
4789  int prev_separator = nk_true;
4790 
4791  /* use "best" matched letter if multiple string letters match the pattern */
4792  char const * best_letter = 0;
4793  int best_letter_score = 0;
4794 
4795  /* loop over strings */
4796  NK_ASSERT(str);
4797  NK_ASSERT(pattern);
4798  if (!str || !str_len || !pattern) return 0;
4799  while (str_iter < str_len)
4800  {
4801  const char pattern_letter = *pattern_iter;
4802  const char str_letter = str[str_iter];
4803 
4804  int next_match = *pattern_iter != '\0' &&
4805  nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
4806  int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
4807 
4808  int advanced = next_match && best_letter;
4809  int pattern_repeat = best_letter && *pattern_iter != '\0';
4810  pattern_repeat = pattern_repeat &&
4811  nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
4812 
4813  if (advanced || pattern_repeat) {
4814  score += best_letter_score;
4815  best_letter = 0;
4816  best_letter_score = 0;
4817  }
4818 
4819  if (next_match || rematch)
4820  {
4821  int new_score = 0;
4822  /* Apply penalty for each letter before the first pattern match */
4823  if (pattern_iter == pattern) {
4824  int count = (int)(&str[str_iter] - str);
4825  int penalty = NK_LEADING_LETTER_PENALTY * count;
4826  if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
4827  penalty = NK_MAX_LEADING_LETTER_PENALTY;
4828 
4829  score += penalty;
4830  }
4831 
4832  /* apply bonus for consecutive bonuses */
4833  if (prev_matched)
4834  new_score += NK_ADJACENCY_BONUS;
4835 
4836  /* apply bonus for matches after a separator */
4837  if (prev_separator)
4838  new_score += NK_SEPARATOR_BONUS;
4839 
4840  /* apply bonus across camel case boundaries */
4841  if (prev_lower && nk_is_upper(str_letter))
4842  new_score += NK_CAMEL_BONUS;
4843 
4844  /* update pattern iter IFF the next pattern letter was matched */
4845  if (next_match)
4846  ++pattern_iter;
4847 
4848  /* update best letter in str which may be for a "next" letter or a rematch */
4849  if (new_score >= best_letter_score) {
4850  /* apply penalty for now skipped letter */
4851  if (best_letter != 0)
4852  score += NK_UNMATCHED_LETTER_PENALTY;
4853 
4854  best_letter = &str[str_iter];
4855  best_letter_score = new_score;
4856  }
4857  prev_matched = nk_true;
4858  } else {
4859  score += NK_UNMATCHED_LETTER_PENALTY;
4860  prev_matched = nk_false;
4861  }
4862 
4863  /* separators should be more easily defined */
4864  prev_lower = nk_is_lower(str_letter) != 0;
4865  prev_separator = str_letter == '_' || str_letter == ' ';
4866 
4867  ++str_iter;
4868  }
4869 
4870  /* apply score for last match */
4871  if (best_letter)
4872  score += best_letter_score;
4873 
4874  /* did not match full pattern */
4875  if (*pattern_iter != '\0')
4876  return nk_false;
4877 
4878  if (out_score)
4879  *out_score = score;
4880  return nk_true;
4881 }
4882 
4883 NK_API int
4884 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
4885 {return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);}
4886 
4887 NK_INTERN int
4888 nk_string_float_limit(char *string, int prec)
4889 {
4890  int dot = 0;
4891  char *c = string;
4892  while (*c) {
4893  if (*c == '.') {
4894  dot = 1;
4895  c++;
4896  continue;
4897  }
4898  if (dot == (prec+1)) {
4899  *c = 0;
4900  break;
4901  }
4902  if (dot > 0) dot++;
4903  c++;
4904  }
4905  return (int)(c - string);
4906 }
4907 
4908 NK_INTERN double
4909 nk_pow(double x, int n)
4910 {
4911  /* check the sign of n */
4912  double r = 1;
4913  int plus = n >= 0;
4914  n = (plus) ? n : -n;
4915  while (n > 0) {
4916  if ((n & 1) == 1)
4917  r *= x;
4918  n /= 2;
4919  x *= x;
4920  }
4921  return plus ? r : 1.0 / r;
4922 }
4923 
4924 NK_INTERN int
4925 nk_ifloord(double x)
4926 {
4927  x = (double)((int)x - ((x < 0.0) ? 1 : 0));
4928  return (int)x;
4929 }
4930 
4931 NK_INTERN int
4932 nk_ifloorf(float x)
4933 {
4934  x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
4935  return (int)x;
4936 }
4937 
4938 NK_INTERN int
4939 nk_iceilf(float x)
4940 {
4941  if (x >= 0) {
4942  int i = (int)x;
4943  return i;
4944  } else {
4945  int t = (int)x;
4946  float r = x - (float)t;
4947  return (r > 0.0f) ? t+1: t;
4948  }
4949 }
4950 
4951 NK_INTERN int
4952 nk_log10(double n)
4953 {
4954  int neg;
4955  int ret;
4956  int exp = 0;
4957 
4958  neg = (n < 0) ? 1 : 0;
4959  ret = (neg) ? (int)-n : (int)n;
4960  while ((ret / 10) > 0) {
4961  ret /= 10;
4962  exp++;
4963  }
4964  if (neg) exp = -exp;
4965  return exp;
4966 }
4967 
4968 NK_INTERN void
4969 nk_strrev_ascii(char *s)
4970 {
4971  int len = nk_strlen(s);
4972  int end = len / 2;
4973  int i = 0;
4974  char t;
4975  for (; i < end; ++i) {
4976  t = s[i];
4977  s[i] = s[len - 1 - i];
4978  s[len -1 - i] = t;
4979  }
4980 }
4981 
4982 NK_INTERN char*
4983 nk_itoa(char *s, long n)
4984 {
4985  long i = 0;
4986  if (n == 0) {
4987  s[i++] = '0';
4988  s[i] = 0;
4989  return s;
4990  }
4991  if (n < 0) {
4992  s[i++] = '-';
4993  n = -n;
4994  }
4995  while (n > 0) {
4996  s[i++] = (char)('0' + (n % 10));
4997  n /= 10;
4998  }
4999  s[i] = 0;
5000  if (s[0] == '-')
5001  ++s;
5002 
5003  nk_strrev_ascii(s);
5004  return s;
5005 }
5006 
5007 NK_INTERN char*
5008 nk_dtoa(char *s, double n)
5009 {
5010  int useExp = 0;
5011  int digit = 0, m = 0, m1 = 0;
5012  char *c = s;
5013  int neg = 0;
5014 
5015  NK_ASSERT(s);
5016  if (!s) return 0;
5017 
5018  if (n == 0.0) {
5019  s[0] = '0'; s[1] = '\0';
5020  return s;
5021  }
5022 
5023  neg = (n < 0);
5024  if (neg) n = -n;
5025 
5026  /* calculate magnitude */
5027  m = nk_log10(n);
5028  useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
5029  if (neg) *(c++) = '-';
5030 
5031  /* set up for scientific notation */
5032  if (useExp) {
5033  if (m < 0)
5034  m -= 1;
5035  n = n / (double)nk_pow(10.0, m);
5036  m1 = m;
5037  m = 0;
5038  }
5039  if (m < 1.0) {
5040  m = 0;
5041  }
5042 
5043  /* convert the number */
5044  while (n > NK_FLOAT_PRECISION || m >= 0) {
5045  double weight = nk_pow(10.0, m);
5046  if (weight > 0) {
5047  double t = (double)n / weight;
5048  digit = nk_ifloord(t);
5049  n -= ((double)digit * weight);
5050  *(c++) = (char)('0' + (char)digit);
5051  }
5052  if (m == 0 && n > 0)
5053  *(c++) = '.';
5054  m--;
5055  }
5056 
5057  if (useExp) {
5058  /* convert the exponent */
5059  int i, j;
5060  *(c++) = 'e';
5061  if (m1 > 0) {
5062  *(c++) = '+';
5063  } else {
5064  *(c++) = '-';
5065  m1 = -m1;
5066  }
5067  m = 0;
5068  while (m1 > 0) {
5069  *(c++) = (char)('0' + (char)(m1 % 10));
5070  m1 /= 10;
5071  m++;
5072  }
5073  c -= m;
5074  for (i = 0, j = m-1; i<j; i++, j--) {
5075  /* swap without temporary */
5076  c[i] ^= c[j];
5077  c[j] ^= c[i];
5078  c[i] ^= c[j];
5079  }
5080  c += m;
5081  }
5082  *(c) = '\0';
5083  return s;
5084 }
5085 
5086 #ifdef NK_INCLUDE_STANDARD_VARARGS
5087 #ifndef NK_INCLUDE_STANDARD_IO
5088 static int
5089 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
5090 {
5091  enum nk_arg_type {
5092  NK_ARG_TYPE_CHAR,
5093  NK_ARG_TYPE_SHORT,
5094  NK_ARG_TYPE_DEFAULT,
5095  NK_ARG_TYPE_LONG
5096  };
5097  enum nk_arg_flags {
5098  NK_ARG_FLAG_LEFT = 0x01,
5099  NK_ARG_FLAG_PLUS = 0x02,
5100  NK_ARG_FLAG_SPACE = 0x04,
5101  NK_ARG_FLAG_NUM = 0x10,
5102  NK_ARG_FLAG_ZERO = 0x20
5103  };
5104 
5105  char number_buffer[NK_MAX_NUMBER_BUFFER];
5106  enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
5107  int precision = NK_DEFAULT;
5108  int width = NK_DEFAULT;
5109  nk_flags flag = 0;
5110 
5111  int len = 0;
5112  int result = -1;
5113  const char *iter = fmt;
5114 
5115  NK_ASSERT(buf);
5116  NK_ASSERT(buf_size);
5117  if (!buf || !buf_size || !fmt) return 0;
5118  for (iter = fmt; *iter && len < buf_size; iter++) {
5119  /* copy all non-format characters */
5120  while (*iter && (*iter != '%') && (len < buf_size))
5121  buf[len++] = *iter++;
5122  if (!(*iter) || len >= buf_size) break;
5123  iter++;
5124 
5125  /* flag arguments */
5126  while (*iter) {
5127  if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
5128  else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
5129  else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
5130  else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
5131  else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
5132  else break;
5133  iter++;
5134  }
5135 
5136  /* width argument */
5137  width = NK_DEFAULT;
5138  if (*iter >= '1' && *iter <= '9') {
5139  const char *end;
5140  width = nk_strtoi(iter, &end);
5141  if (end == iter)
5142  width = -1;
5143  else iter = end;
5144  } else if (*iter == '*') {
5145  width = va_arg(args, int);
5146  iter++;
5147  }
5148 
5149  /* precision argument */
5150  precision = NK_DEFAULT;
5151  if (*iter == '.') {
5152  iter++;
5153  if (*iter == '*') {
5154  precision = va_arg(args, int);
5155  iter++;
5156  } else {
5157  const char *end;
5158  precision = nk_strtoi(iter, &end);
5159  if (end == iter)
5160  precision = -1;
5161  else iter = end;
5162  }
5163  }
5164 
5165  /* length modifier */
5166  if (*iter == 'h') {
5167  if (*(iter+1) == 'h') {
5168  arg_type = NK_ARG_TYPE_CHAR;
5169  iter++;
5170  } else arg_type = NK_ARG_TYPE_SHORT;
5171  iter++;
5172  } else if (*iter == 'l') {
5173  arg_type = NK_ARG_TYPE_LONG;
5174  iter++;
5175  } else arg_type = NK_ARG_TYPE_DEFAULT;
5176 
5177  /* specifier */
5178  if (*iter == '%') {
5179  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5180  NK_ASSERT(precision == NK_DEFAULT);
5181  NK_ASSERT(width == NK_DEFAULT);
5182  if (len < buf_size)
5183  buf[len++] = '%';
5184  } else if (*iter == 's') {
5185  /* string */
5186  const char *str = va_arg(args, const char*);
5187  NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
5188  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5189  NK_ASSERT(precision == NK_DEFAULT);
5190  NK_ASSERT(width == NK_DEFAULT);
5191  if (str == buf) return -1;
5192  while (str && *str && len < buf_size)
5193  buf[len++] = *str++;
5194  } else if (*iter == 'n') {
5195  /* current length callback */
5196  signed int *n = va_arg(args, int*);
5197  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5198  NK_ASSERT(precision == NK_DEFAULT);
5199  NK_ASSERT(width == NK_DEFAULT);
5200  if (n) *n = len;
5201  } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
5202  /* signed integer */
5203  long value = 0;
5204  const char *num_iter;
5205  int num_len, num_print, padding;
5206  int cur_precision = NK_MAX(precision, 1);
5207  int cur_width = NK_MAX(width, 0);
5208 
5209  /* retrieve correct value type */
5210  if (arg_type == NK_ARG_TYPE_CHAR)
5211  value = (signed char)va_arg(args, int);
5212  else if (arg_type == NK_ARG_TYPE_SHORT)
5213  value = (signed short)va_arg(args, int);
5214  else if (arg_type == NK_ARG_TYPE_LONG)
5215  value = va_arg(args, signed long);
5216  else if (*iter == 'c')
5217  value = (unsigned char)va_arg(args, int);
5218  else value = va_arg(args, signed int);
5219 
5220  /* convert number to string */
5221  nk_itoa(number_buffer, value);
5222  num_len = nk_strlen(number_buffer);
5223  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
5224  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
5225  padding = NK_MAX(padding-1, 0);
5226 
5227  /* fill left padding up to a total of `width` characters */
5228  if (!(flag & NK_ARG_FLAG_LEFT)) {
5229  while (padding-- > 0 && (len < buf_size)) {
5230  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
5231  buf[len++] = '0';
5232  else buf[len++] = ' ';
5233  }
5234  }
5235 
5236  /* copy string value representation into buffer */
5237  if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
5238  buf[len++] = '+';
5239  else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
5240  buf[len++] = ' ';
5241 
5242  /* fill up to precision number of digits with '0' */
5243  num_print = NK_MAX(cur_precision, num_len);
5244  while (precision && (num_print > num_len) && (len < buf_size)) {
5245  buf[len++] = '0';
5246  num_print--;
5247  }
5248 
5249  /* copy string value representation into buffer */
5250  num_iter = number_buffer;
5251  while (precision && *num_iter && len < buf_size)
5252  buf[len++] = *num_iter++;
5253 
5254  /* fill right padding up to width characters */
5255  if (flag & NK_ARG_FLAG_LEFT) {
5256  while ((padding-- > 0) && (len < buf_size))
5257  buf[len++] = ' ';
5258  }
5259  } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
5260  /* unsigned integer */
5261  unsigned long value = 0;
5262  int num_len = 0, num_print, padding = 0;
5263  int cur_precision = NK_MAX(precision, 1);
5264  int cur_width = NK_MAX(width, 0);
5265  unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
5266 
5267  /* print oct/hex/dec value */
5268  const char *upper_output_format = "0123456789ABCDEF";
5269  const char *lower_output_format = "0123456789abcdef";
5270  const char *output_format = (*iter == 'x') ?
5271  lower_output_format: upper_output_format;
5272 
5273  /* retrieve correct value type */
5274  if (arg_type == NK_ARG_TYPE_CHAR)
5275  value = (unsigned char)va_arg(args, int);
5276  else if (arg_type == NK_ARG_TYPE_SHORT)
5277  value = (unsigned short)va_arg(args, int);
5278  else if (arg_type == NK_ARG_TYPE_LONG)
5279  value = va_arg(args, unsigned long);
5280  else value = va_arg(args, unsigned int);
5281 
5282  do {
5283  /* convert decimal number into hex/oct number */
5284  int digit = output_format[value % base];
5285  if (num_len < NK_MAX_NUMBER_BUFFER)
5286  number_buffer[num_len++] = (char)digit;
5287  value /= base;
5288  } while (value > 0);
5289 
5290  num_print = NK_MAX(cur_precision, num_len);
5291  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
5292  if (flag & NK_ARG_FLAG_NUM)
5293  padding = NK_MAX(padding-1, 0);
5294 
5295  /* fill left padding up to a total of `width` characters */
5296  if (!(flag & NK_ARG_FLAG_LEFT)) {
5297  while ((padding-- > 0) && (len < buf_size)) {
5298  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
5299  buf[len++] = '0';
5300  else buf[len++] = ' ';
5301  }
5302  }
5303 
5304  /* fill up to precision number of digits */
5305  if (num_print && (flag & NK_ARG_FLAG_NUM)) {
5306  if ((*iter == 'o') && (len < buf_size)) {
5307  buf[len++] = '0';
5308  } else if ((*iter == 'x') && ((len+1) < buf_size)) {
5309  buf[len++] = '0';
5310  buf[len++] = 'x';
5311  } else if ((*iter == 'X') && ((len+1) < buf_size)) {
5312  buf[len++] = '0';
5313  buf[len++] = 'X';
5314  }
5315  }
5316  while (precision && (num_print > num_len) && (len < buf_size)) {
5317  buf[len++] = '0';
5318  num_print--;
5319  }
5320 
5321  /* reverse number direction */
5322  while (num_len > 0) {
5323  if (precision && (len < buf_size))
5324  buf[len++] = number_buffer[num_len-1];
5325  num_len--;
5326  }
5327 
5328  /* fill right padding up to width characters */
5329  if (flag & NK_ARG_FLAG_LEFT) {
5330  while ((padding-- > 0) && (len < buf_size))
5331  buf[len++] = ' ';
5332  }
5333  } else if (*iter == 'f') {
5334  /* floating point */
5335  const char *num_iter;
5336  int cur_precision = (precision < 0) ? 6: precision;
5337  int prefix, cur_width = NK_MAX(width, 0);
5338  double value = va_arg(args, double);
5339  int num_len = 0, frac_len = 0, dot = 0;
5340  int padding = 0;
5341 
5342  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5343  NK_DTOA(number_buffer, value);
5344  num_len = nk_strlen(number_buffer);
5345 
5346  /* calculate padding */
5347  num_iter = number_buffer;
5348  while (*num_iter && *num_iter != '.')
5349  num_iter++;
5350 
5351  prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
5352  padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
5353  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
5354  padding = NK_MAX(padding-1, 0);
5355 
5356  /* fill left padding up to a total of `width` characters */
5357  if (!(flag & NK_ARG_FLAG_LEFT)) {
5358  while (padding-- > 0 && (len < buf_size)) {
5359  if (flag & NK_ARG_FLAG_ZERO)
5360  buf[len++] = '0';
5361  else buf[len++] = ' ';
5362  }
5363  }
5364 
5365  /* copy string value representation into buffer */
5366  num_iter = number_buffer;
5367  if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
5368  buf[len++] = '+';
5369  else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
5370  buf[len++] = ' ';
5371  while (*num_iter) {
5372  if (dot) frac_len++;
5373  if (len < buf_size)
5374  buf[len++] = *num_iter;
5375  if (*num_iter == '.') dot = 1;
5376  if (frac_len >= cur_precision) break;
5377  num_iter++;
5378  }
5379 
5380  /* fill number up to precision */
5381  while (frac_len < cur_precision) {
5382  if (!dot && len < buf_size) {
5383  buf[len++] = '.';
5384  dot = 1;
5385  }
5386  if (len < buf_size)
5387  buf[len++] = '0';
5388  frac_len++;
5389  }
5390 
5391  /* fill right padding up to width characters */
5392  if (flag & NK_ARG_FLAG_LEFT) {
5393  while ((padding-- > 0) && (len < buf_size))
5394  buf[len++] = ' ';
5395  }
5396  } else {
5397  /* Specifier not supported: g,G,e,E,p,z */
5398  NK_ASSERT(0 && "specifier is not supported!");
5399  return result;
5400  }
5401  }
5402  buf[(len >= buf_size)?(buf_size-1):len] = 0;
5403  result = (len >= buf_size)?-1:len;
5404  return result;
5405 }
5406 #endif
5407 
5408 NK_INTERN int
5409 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
5410 {
5411  int result = -1;
5412  NK_ASSERT(buf);
5413  NK_ASSERT(buf_size);
5414  if (!buf || !buf_size || !fmt) return 0;
5415 #ifdef NK_INCLUDE_STANDARD_IO
5416  result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
5417  result = (result >= buf_size) ? -1: result;
5418  buf[buf_size-1] = 0;
5419 #else
5420  result = nk_vsnprintf(buf, buf_size, fmt, args);
5421 #endif
5422  return result;
5423 }
5424 #endif
5425 
5426 NK_API nk_hash
5427 nk_murmur_hash(const void * key, int len, nk_hash seed)
5428 {
5429  /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
5430  #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
5431  union {const nk_uint *i; const nk_byte *b;} conv = {0};
5432  const nk_byte *data = (const nk_byte*)key;
5433  const int nblocks = len/4;
5434  nk_uint h1 = seed;
5435  const nk_uint c1 = 0xcc9e2d51;
5436  const nk_uint c2 = 0x1b873593;
5437  const nk_byte *tail;
5438  const nk_uint *blocks;
5439  nk_uint k1;
5440  int i;
5441 
5442  /* body */
5443  if (!key) return 0;
5444  conv.b = (data + nblocks*4);
5445  blocks = (const nk_uint*)conv.i;
5446  for (i = -nblocks; i; ++i) {
5447  k1 = blocks[i];
5448  k1 *= c1;
5449  k1 = NK_ROTL(k1,15);
5450  k1 *= c2;
5451 
5452  h1 ^= k1;
5453  h1 = NK_ROTL(h1,13);
5454  h1 = h1*5+0xe6546b64;
5455  }
5456 
5457  /* tail */
5458  tail = (const nk_byte*)(data + nblocks*4);
5459  k1 = 0;
5460  switch (len & 3) {
5461  case 3: k1 ^= (nk_uint)(tail[2] << 16);
5462  case 2: k1 ^= (nk_uint)(tail[1] << 8u);
5463  case 1: k1 ^= tail[0];
5464  k1 *= c1;
5465  k1 = NK_ROTL(k1,15);
5466  k1 *= c2;
5467  h1 ^= k1;
5468  default: break;
5469  }
5470 
5471  /* finalization */
5472  h1 ^= (nk_uint)len;
5473  /* fmix32 */
5474  h1 ^= h1 >> 16;
5475  h1 *= 0x85ebca6b;
5476  h1 ^= h1 >> 13;
5477  h1 *= 0xc2b2ae35;
5478  h1 ^= h1 >> 16;
5479 
5480  #undef NK_ROTL
5481  return h1;
5482 }
5483 
5484 #ifdef NK_INCLUDE_STANDARD_IO
5485 NK_INTERN char*
5486 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
5487 {
5488  char *buf;
5489  FILE *fd;
5490  long ret;
5491 
5492  NK_ASSERT(path);
5493  NK_ASSERT(siz);
5494  NK_ASSERT(alloc);
5495  if (!path || !siz || !alloc)
5496  return 0;
5497 
5498  fd = fopen(path, "rb");
5499  if (!fd) return 0;
5500  fseek(fd, 0, SEEK_END);
5501  ret = ftell(fd);
5502  if (ret < 0) {
5503  fclose(fd);
5504  return 0;
5505  }
5506  *siz = (nk_size)ret;
5507  fseek(fd, 0, SEEK_SET);
5508  buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
5509  NK_ASSERT(buf);
5510  if (!buf) {
5511  fclose(fd);
5512  return 0;
5513  }
5514  *siz = (nk_size)fread(buf, *siz, 1, fd);
5515  fclose(fd);
5516  return buf;
5517 }
5518 #endif
5519 
5520 /*
5521  * ==============================================================
5522  *
5523  * COLOR
5524  *
5525  * ===============================================================
5526  */
5527 NK_INTERN int
5528 nk_parse_hex(const char *p, int length)
5529 {
5530  int i = 0;
5531  int len = 0;
5532  while (len < length) {
5533  i <<= 4;
5534  if (p[len] >= 'a' && p[len] <= 'f')
5535  i += ((p[len] - 'a') + 10);
5536  else if (p[len] >= 'A' && p[len] <= 'F')
5537  i += ((p[len] - 'A') + 10);
5538  else i += (p[len] - '0');
5539  len++;
5540  }
5541  return i;
5542 }
5543 
5544 NK_API struct nk_color
5545 nk_rgba(int r, int g, int b, int a)
5546 {
5547  struct nk_color ret;
5548  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
5549  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
5550  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
5551  ret.a = (nk_byte)NK_CLAMP(0, a, 255);
5552  return ret;
5553 }
5554 
5555 NK_API struct nk_color
5556 nk_rgb_hex(const char *rgb)
5557 {
5558  struct nk_color col;
5559  const char *c = rgb;
5560  if (*c == '#') c++;
5561  col.r = (nk_byte)nk_parse_hex(c, 2);
5562  col.g = (nk_byte)nk_parse_hex(c+2, 2);
5563  col.b = (nk_byte)nk_parse_hex(c+4, 2);
5564  col.a = 255;
5565  return col;
5566 }
5567 
5568 NK_API struct nk_color
5569 nk_rgba_hex(const char *rgb)
5570 {
5571  struct nk_color col;
5572  const char *c = rgb;
5573  if (*c == '#') c++;
5574  col.r = (nk_byte)nk_parse_hex(c, 2);
5575  col.g = (nk_byte)nk_parse_hex(c+2, 2);
5576  col.b = (nk_byte)nk_parse_hex(c+4, 2);
5577  col.a = (nk_byte)nk_parse_hex(c+6, 2);
5578  return col;
5579 }
5580 
5581 NK_API void
5582 nk_color_hex_rgba(char *output, struct nk_color col)
5583 {
5584  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
5585  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
5586  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
5587  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
5588  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
5589  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
5590  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
5591  output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
5592  output[7] = (char)NK_TO_HEX((col.a & 0x0F));
5593  output[8] = '\0';
5594  #undef NK_TO_HEX
5595 }
5596 
5597 NK_API void
5598 nk_color_hex_rgb(char *output, struct nk_color col)
5599 {
5600  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
5601  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
5602  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
5603  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
5604  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
5605  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
5606  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
5607  output[6] = '\0';
5608  #undef NK_TO_HEX
5609 }
5610 
5611 NK_API struct nk_color
5612 nk_rgba_iv(const int *c)
5613 {
5614  return nk_rgba(c[0], c[1], c[2], c[3]);
5615 }
5616 
5617 NK_API struct nk_color
5618 nk_rgba_bv(const nk_byte *c)
5619 {
5620  return nk_rgba(c[0], c[1], c[2], c[3]);
5621 }
5622 
5623 NK_API struct nk_color
5624 nk_rgb(int r, int g, int b)
5625 {
5626  struct nk_color ret;
5627  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
5628  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
5629  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
5630  ret.a = (nk_byte)255;
5631  return ret;
5632 }
5633 
5634 NK_API struct nk_color
5635 nk_rgb_iv(const int *c)
5636 {
5637  return nk_rgb(c[0], c[1], c[2]);
5638 }
5639 
5640 NK_API struct nk_color
5641 nk_rgb_bv(const nk_byte* c)
5642 {
5643  return nk_rgb(c[0], c[1], c[2]);
5644 }
5645 
5646 NK_API struct nk_color
5647 nk_rgba_u32(nk_uint in)
5648 {
5649  struct nk_color ret;
5650  ret.r = (in & 0xFF);
5651  ret.g = ((in >> 8) & 0xFF);
5652  ret.b = ((in >> 16) & 0xFF);
5653  ret.a = (nk_byte)((in >> 24) & 0xFF);
5654  return ret;
5655 }
5656 
5657 NK_API struct nk_color
5658 nk_rgba_f(float r, float g, float b, float a)
5659 {
5660  struct nk_color ret;
5661  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
5662  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
5663  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
5664  ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
5665  return ret;
5666 }
5667 
5668 NK_API struct nk_color
5669 nk_rgba_fv(const float *c)
5670 {
5671  return nk_rgba_f(c[0], c[1], c[2], c[3]);
5672 }
5673 
5674 NK_API struct nk_color
5675 nk_rgb_f(float r, float g, float b)
5676 {
5677  struct nk_color ret;
5678  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
5679  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
5680  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
5681  ret.a = 255;
5682  return ret;
5683 }
5684 
5685 NK_API struct nk_color
5686 nk_rgb_fv(const float *c)
5687 {
5688  return nk_rgb_f(c[0], c[1], c[2]);
5689 }
5690 
5691 NK_API struct nk_color
5692 nk_hsv(int h, int s, int v)
5693 {
5694  return nk_hsva(h, s, v, 255);
5695 }
5696 
5697 NK_API struct nk_color
5698 nk_hsv_iv(const int *c)
5699 {
5700  return nk_hsv(c[0], c[1], c[2]);
5701 }
5702 
5703 NK_API struct nk_color
5704 nk_hsv_bv(const nk_byte *c)
5705 {
5706  return nk_hsv(c[0], c[1], c[2]);
5707 }
5708 
5709 NK_API struct nk_color
5710 nk_hsv_f(float h, float s, float v)
5711 {
5712  return nk_hsva_f(h, s, v, 1.0f);
5713 }
5714 
5715 NK_API struct nk_color
5716 nk_hsv_fv(const float *c)
5717 {
5718  return nk_hsv_f(c[0], c[1], c[2]);
5719 }
5720 
5721 NK_API struct nk_color
5722 nk_hsva(int h, int s, int v, int a)
5723 {
5724  float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
5725  float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
5726  float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
5727  float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
5728  return nk_hsva_f(hf, sf, vf, af);
5729 }
5730 
5731 NK_API struct nk_color
5732 nk_hsva_iv(const int *c)
5733 {
5734  return nk_hsva(c[0], c[1], c[2], c[3]);
5735 }
5736 
5737 NK_API struct nk_color
5738 nk_hsva_bv(const nk_byte *c)
5739 {
5740  return nk_hsva(c[0], c[1], c[2], c[3]);
5741 }
5742 
5743 NK_API struct nk_color
5744 nk_hsva_f(float h, float s, float v, float a)
5745 {
5746  struct nk_colorf out = {0,0,0,0};
5747  float p, q, t, f;
5748  int i;
5749 
5750  if (s <= 0.0f) {
5751  out.r = v; out.g = v; out.b = v;
5752  return nk_rgb_f(out.r, out.g, out.b);
5753  }
5754 
5755  h = h / (60.0f/360.0f);
5756  i = (int)h;
5757  f = h - (float)i;
5758  p = v * (1.0f - s);
5759  q = v * (1.0f - (s * f));
5760  t = v * (1.0f - s * (1.0f - f));
5761 
5762  switch (i) {
5763  case 0: default: out.r = v; out.g = t; out.b = p; break;
5764  case 1: out.r = q; out.g = v; out.b = p; break;
5765  case 2: out.r = p; out.g = v; out.b = t; break;
5766  case 3: out.r = p; out.g = q; out.b = v; break;
5767  case 4: out.r = t; out.g = p; out.b = v; break;
5768  case 5: out.r = v; out.g = p; out.b = q; break;
5769  }
5770  return nk_rgba_f(out.r, out.g, out.b, a);
5771 }
5772 
5773 NK_API struct nk_color
5774 nk_hsva_fv(const float *c)
5775 {
5776  return nk_hsva_f(c[0], c[1], c[2], c[3]);
5777 }
5778 
5779 NK_API nk_uint
5780 nk_color_u32(struct nk_color in)
5781 {
5782  nk_uint out = (nk_uint)in.r;
5783  out |= ((nk_uint)in.g << 8);
5784  out |= ((nk_uint)in.b << 16);
5785  out |= ((nk_uint)in.a << 24);
5786  return out;
5787 }
5788 
5789 NK_API void
5790 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
5791 {
5792  NK_STORAGE const float s = 1.0f/255.0f;
5793  *r = (float)in.r * s;
5794  *g = (float)in.g * s;
5795  *b = (float)in.b * s;
5796  *a = (float)in.a * s;
5797 }
5798 
5799 NK_API void
5800 nk_color_fv(float *c, struct nk_color in)
5801 {
5802  nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
5803 }
5804 
5805 NK_API void
5806 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
5807 {
5808  NK_STORAGE const double s = 1.0/255.0;
5809  *r = (double)in.r * s;
5810  *g = (double)in.g * s;
5811  *b = (double)in.b * s;
5812  *a = (double)in.a * s;
5813 }
5814 
5815 NK_API void
5816 nk_color_dv(double *c, struct nk_color in)
5817 {
5818  nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
5819 }
5820 
5821 NK_API void
5822 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
5823 {
5824  float a;
5825  nk_color_hsva_f(out_h, out_s, out_v, &a, in);
5826 }
5827 
5828 NK_API void
5829 nk_color_hsv_fv(float *out, struct nk_color in)
5830 {
5831  float a;
5832  nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
5833 }
5834 
5835 NK_API void
5836 nk_color_hsva_f(float *out_h, float *out_s,
5837  float *out_v, float *out_a, struct nk_color in)
5838 {
5839  float chroma;
5840  float K = 0.0f;
5841  float r,g,b,a;
5842 
5843  nk_color_f(&r,&g,&b,&a, in);
5844  if (g < b) {
5845  const float t = g; g = b; b = t;
5846  K = -1.f;
5847  }
5848  if (r < g) {
5849  const float t = r; r = g; g = t;
5850  K = -2.f/6.0f - K;
5851  }
5852  chroma = r - ((g < b) ? g: b);
5853  *out_h = NK_ABS(K + (g - b)/(6.0f * chroma + 1e-20f));
5854  *out_s = chroma / (r + 1e-20f);
5855  *out_v = r;
5856  *out_a = (float)in.a / 255.0f;
5857 }
5858 
5859 NK_API void
5860 nk_color_hsva_fv(float *out, struct nk_color in)
5861 {
5862  nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
5863 }
5864 
5865 NK_API void
5866 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
5867  int *out_a, struct nk_color in)
5868 {
5869  float h,s,v,a;
5870  nk_color_hsva_f(&h, &s, &v, &a, in);
5871  *out_h = (nk_byte)(h * 255.0f);
5872  *out_s = (nk_byte)(s * 255.0f);
5873  *out_v = (nk_byte)(v * 255.0f);
5874  *out_a = (nk_byte)(a * 255.0f);
5875 }
5876 
5877 NK_API void
5878 nk_color_hsva_iv(int *out, struct nk_color in)
5879 {
5880  nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
5881 }
5882 
5883 NK_API void
5884 nk_color_hsva_bv(nk_byte *out, struct nk_color in)
5885 {
5886  int tmp[4];
5887  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
5888  out[0] = (nk_byte)tmp[0];
5889  out[1] = (nk_byte)tmp[1];
5890  out[2] = (nk_byte)tmp[2];
5891  out[3] = (nk_byte)tmp[3];
5892 }
5893 
5894 NK_API void
5895 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
5896 {
5897  int tmp[4];
5898  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
5899  *h = (nk_byte)tmp[0];
5900  *s = (nk_byte)tmp[1];
5901  *v = (nk_byte)tmp[2];
5902  *a = (nk_byte)tmp[3];
5903 }
5904 
5905 NK_API void
5906 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
5907 {
5908  int a;
5909  nk_color_hsva_i(out_h, out_s, out_v, &a, in);
5910 }
5911 
5912 NK_API void
5913 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
5914 {
5915  int tmp[4];
5916  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
5917  *out_h = (nk_byte)tmp[0];
5918  *out_s = (nk_byte)tmp[1];
5919  *out_v = (nk_byte)tmp[2];
5920 }
5921 
5922 NK_API void
5923 nk_color_hsv_iv(int *out, struct nk_color in)
5924 {
5925  nk_color_hsv_i(&out[0], &out[1], &out[2], in);
5926 }
5927 
5928 NK_API void
5929 nk_color_hsv_bv(nk_byte *out, struct nk_color in)
5930 {
5931  int tmp[4];
5932  nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
5933  out[0] = (nk_byte)tmp[0];
5934  out[1] = (nk_byte)tmp[1];
5935  out[2] = (nk_byte)tmp[2];
5936 }
5937 /*
5938  * ==============================================================
5939  *
5940  * IMAGE
5941  *
5942  * ===============================================================
5943  */
5944 NK_API nk_handle
5945 nk_handle_ptr(void *ptr)
5946 {
5947  nk_handle handle = {0};
5948  handle.ptr = ptr;
5949  return handle;
5950 }
5951 
5952 NK_API nk_handle
5953 nk_handle_id(int id)
5954 {
5955  nk_handle handle;
5956  nk_zero_struct(handle);
5957  handle.id = id;
5958  return handle;
5959 }
5960 
5961 NK_API struct nk_image
5962 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r)
5963 {
5964  struct nk_image s;
5965  nk_zero(&s, sizeof(s));
5966  s.handle.ptr = ptr;
5967  s.w = w; s.h = h;
5968  s.region[0] = (unsigned short)r.x;
5969  s.region[1] = (unsigned short)r.y;
5970  s.region[2] = (unsigned short)r.w;
5971  s.region[3] = (unsigned short)r.h;
5972  return s;
5973 }
5974 
5975 NK_API struct nk_image
5976 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r)
5977 {
5978  struct nk_image s;
5979  nk_zero(&s, sizeof(s));
5980  s.handle.id = id;
5981  s.w = w; s.h = h;
5982  s.region[0] = (unsigned short)r.x;
5983  s.region[1] = (unsigned short)r.y;
5984  s.region[2] = (unsigned short)r.w;
5985  s.region[3] = (unsigned short)r.h;
5986  return s;
5987 }
5988 
5989 NK_API struct nk_image
5990 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h,
5991  struct nk_rect r)
5992 {
5993  struct nk_image s;
5994  nk_zero(&s, sizeof(s));
5995  s.handle = handle;
5996  s.w = w; s.h = h;
5997  s.region[0] = (unsigned short)r.x;
5998  s.region[1] = (unsigned short)r.y;
5999  s.region[2] = (unsigned short)r.w;
6000  s.region[3] = (unsigned short)r.h;
6001  return s;
6002 }
6003 
6004 NK_API struct nk_image
6005 nk_image_handle(nk_handle handle)
6006 {
6007  struct nk_image s;
6008  nk_zero(&s, sizeof(s));
6009  s.handle = handle;
6010  s.w = 0; s.h = 0;
6011  s.region[0] = 0;
6012  s.region[1] = 0;
6013  s.region[2] = 0;
6014  s.region[3] = 0;
6015  return s;
6016 }
6017 
6018 NK_API struct nk_image
6019 nk_image_ptr(void *ptr)
6020 {
6021  struct nk_image s;
6022  nk_zero(&s, sizeof(s));
6023  NK_ASSERT(ptr);
6024  s.handle.ptr = ptr;
6025  s.w = 0; s.h = 0;
6026  s.region[0] = 0;
6027  s.region[1] = 0;
6028  s.region[2] = 0;
6029  s.region[3] = 0;
6030  return s;
6031 }
6032 
6033 NK_API struct nk_image
6034 nk_image_id(int id)
6035 {
6036  struct nk_image s;
6037  nk_zero(&s, sizeof(s));
6038  s.handle.id = id;
6039  s.w = 0; s.h = 0;
6040  s.region[0] = 0;
6041  s.region[1] = 0;
6042  s.region[2] = 0;
6043  s.region[3] = 0;
6044  return s;
6045 }
6046 
6047 NK_API int
6048 nk_image_is_subimage(const struct nk_image* img)
6049 {
6050  NK_ASSERT(img);
6051  return !(img->w == 0 && img->h == 0);
6052 }
6053 
6054 NK_INTERN void
6055 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
6056  float x1, float y1)
6057 {
6058  NK_ASSERT(a);
6059  NK_ASSERT(clip);
6060  clip->x = NK_MAX(a->x, x0);
6061  clip->y = NK_MAX(a->y, y0);
6062  clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
6063  clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
6064  clip->w = NK_MAX(0, clip->w);
6065  clip->h = NK_MAX(0, clip->h);
6066 }
6067 
6068 NK_API void
6069 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
6070  float pad_x, float pad_y, enum nk_heading direction)
6071 {
6072  float w_half, h_half;
6073  NK_ASSERT(result);
6074 
6075  r.w = NK_MAX(2 * pad_x, r.w);
6076  r.h = NK_MAX(2 * pad_y, r.h);
6077  r.w = r.w - 2 * pad_x;
6078  r.h = r.h - 2 * pad_y;
6079 
6080  r.x = r.x + pad_x;
6081  r.y = r.y + pad_y;
6082 
6083  w_half = r.w / 2.0f;
6084  h_half = r.h / 2.0f;
6085 
6086  if (direction == NK_UP) {
6087  result[0] = nk_vec2(r.x + w_half, r.y);
6088  result[1] = nk_vec2(r.x + r.w, r.y + r.h);
6089  result[2] = nk_vec2(r.x, r.y + r.h);
6090  } else if (direction == NK_RIGHT) {
6091  result[0] = nk_vec2(r.x, r.y);
6092  result[1] = nk_vec2(r.x + r.w, r.y + h_half);
6093  result[2] = nk_vec2(r.x, r.y + r.h);
6094  } else if (direction == NK_DOWN) {
6095  result[0] = nk_vec2(r.x, r.y);
6096  result[1] = nk_vec2(r.x + r.w, r.y);
6097  result[2] = nk_vec2(r.x + w_half, r.y + r.h);
6098  } else {
6099  result[0] = nk_vec2(r.x, r.y + h_half);
6100  result[1] = nk_vec2(r.x + r.w, r.y);
6101  result[2] = nk_vec2(r.x + r.w, r.y + r.h);
6102  }
6103 }
6104 
6105 NK_INTERN int
6106 nk_text_clamp(const struct nk_user_font *font, const char *text,
6107  int text_len, float space, int *glyphs, float *text_width,
6108  nk_rune *sep_list, int sep_count)
6109 {
6110  int i = 0;
6111  int glyph_len = 0;
6112  float last_width = 0;
6113  nk_rune unicode = 0;
6114  float width = 0;
6115  int len = 0;
6116  int g = 0;
6117  float s;
6118 
6119  int sep_len = 0;
6120  int sep_g = 0;
6121  float sep_width = 0;
6122  sep_count = NK_MAX(sep_count,0);
6123 
6124  glyph_len = nk_utf_decode(text, &unicode, text_len);
6125  while (glyph_len && (width < space) && (len < text_len)) {
6126  len += glyph_len;
6127  s = font->width(font->userdata, font->height, text, len);
6128  for (i = 0; i < sep_count; ++i) {
6129  if (unicode != sep_list[i]) continue;
6130  sep_width = last_width = width;
6131  sep_g = g+1;
6132  sep_len = len;
6133  break;
6134  }
6135  if (i == NK_MAX(sep_count,0)){
6136  last_width = sep_width = width;
6137  sep_g = g+1;
6138  }
6139  width = s;
6140  glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
6141  g++;
6142  }
6143  if (len >= text_len) {
6144  *glyphs = g;
6145  *text_width = last_width;
6146  return len;
6147  } else {
6148  *glyphs = sep_g;
6149  *text_width = sep_width;
6150  return (!sep_len) ? len: sep_len;
6151  }
6152 }
6153 
6154 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
6155 NK_INTERN struct nk_vec2
6156 nk_text_calculate_text_bounds(const struct nk_user_font *font,
6157  const char *begin, int byte_len, float row_height, const char **remaining,
6158  struct nk_vec2 *out_offset, int *glyphs, int op)
6159 {
6160  float line_height = row_height;
6161  struct nk_vec2 text_size = nk_vec2(0,0);
6162  float line_width = 0.0f;
6163 
6164  float glyph_width;
6165  int glyph_len = 0;
6166  nk_rune unicode = 0;
6167  int text_len = 0;
6168  if (!begin || byte_len <= 0 || !font)
6169  return nk_vec2(0,row_height);
6170 
6171  glyph_len = nk_utf_decode(begin, &unicode, byte_len);
6172  if (!glyph_len) return text_size;
6173  glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
6174 
6175  *glyphs = 0;
6176  while ((text_len < byte_len) && glyph_len) {
6177  if (unicode == '\n') {
6178  text_size.x = NK_MAX(text_size.x, line_width);
6179  text_size.y += line_height;
6180  line_width = 0;
6181  *glyphs+=1;
6182  if (op == NK_STOP_ON_NEW_LINE)
6183  break;
6184 
6185  text_len++;
6186  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6187  continue;
6188  }
6189 
6190  if (unicode == '\r') {
6191  text_len++;
6192  *glyphs+=1;
6193  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6194  continue;
6195  }
6196 
6197  *glyphs = *glyphs + 1;
6198  text_len += glyph_len;
6199  line_width += (float)glyph_width;
6200  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6201  glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
6202  continue;
6203  }
6204 
6205  if (text_size.x < line_width)
6206  text_size.x = line_width;
6207  if (out_offset)
6208  *out_offset = nk_vec2(line_width, text_size.y + line_height);
6209  if (line_width > 0 || text_size.y == 0.0f)
6210  text_size.y += line_height;
6211  if (remaining)
6212  *remaining = begin+text_len;
6213  return text_size;
6214 }
6215 
6216 /* ==============================================================
6217  *
6218  * UTF-8
6219  *
6220  * ===============================================================*/
6221 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
6222 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
6223 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
6224 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
6225 
6226 NK_INTERN int
6227 nk_utf_validate(nk_rune *u, int i)
6228 {
6229  NK_ASSERT(u);
6230  if (!u) return 0;
6231  if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
6232  NK_BETWEEN(*u, 0xD800, 0xDFFF))
6233  *u = NK_UTF_INVALID;
6234  for (i = 1; *u > nk_utfmax[i]; ++i);
6235  return i;
6236 }
6237 
6238 NK_INTERN nk_rune
6239 nk_utf_decode_byte(char c, int *i)
6240 {
6241  NK_ASSERT(i);
6242  if (!i) return 0;
6243  for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
6244  if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
6245  return (nk_byte)(c & ~nk_utfmask[*i]);
6246  }
6247  return 0;
6248 }
6249 
6250 NK_API int
6251 nk_utf_decode(const char *c, nk_rune *u, int clen)
6252 {
6253  int i, j, len, type=0;
6254  nk_rune udecoded;
6255 
6256  NK_ASSERT(c);
6257  NK_ASSERT(u);
6258 
6259  if (!c || !u) return 0;
6260  if (!clen) return 0;
6261  *u = NK_UTF_INVALID;
6262 
6263  udecoded = nk_utf_decode_byte(c[0], &len);
6264  if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
6265  return 1;
6266 
6267  for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
6268  udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
6269  if (type != 0)
6270  return j;
6271  }
6272  if (j < len)
6273  return 0;
6274  *u = udecoded;
6275  nk_utf_validate(u, len);
6276  return len;
6277 }
6278 
6279 NK_INTERN char
6280 nk_utf_encode_byte(nk_rune u, int i)
6281 {
6282  return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
6283 }
6284 
6285 NK_API int
6286 nk_utf_encode(nk_rune u, char *c, int clen)
6287 {
6288  int len, i;
6289  len = nk_utf_validate(&u, 0);
6290  if (clen < len || !len || len > NK_UTF_SIZE)
6291  return 0;
6292 
6293  for (i = len - 1; i != 0; --i) {
6294  c[i] = nk_utf_encode_byte(u, 0);
6295  u >>= 6;
6296  }
6297  c[0] = nk_utf_encode_byte(u, len);
6298  return len;
6299 }
6300 
6301 NK_API int
6302 nk_utf_len(const char *str, int len)
6303 {
6304  const char *text;
6305  int glyphs = 0;
6306  int text_len;
6307  int glyph_len;
6308  int src_len = 0;
6309  nk_rune unicode;
6310 
6311  NK_ASSERT(str);
6312  if (!str || !len) return 0;
6313 
6314  text = str;
6315  text_len = len;
6316  glyph_len = nk_utf_decode(text, &unicode, text_len);
6317  while (glyph_len && src_len < len) {
6318  glyphs++;
6319  src_len = src_len + glyph_len;
6320  glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
6321  }
6322  return glyphs;
6323 }
6324 
6325 NK_API const char*
6326 nk_utf_at(const char *buffer, int length, int index,
6327  nk_rune *unicode, int *len)
6328 {
6329  int i = 0;
6330  int src_len = 0;
6331  int glyph_len = 0;
6332  const char *text;
6333  int text_len;
6334 
6335  NK_ASSERT(buffer);
6336  NK_ASSERT(unicode);
6337  NK_ASSERT(len);
6338 
6339  if (!buffer || !unicode || !len) return 0;
6340  if (index < 0) {
6341  *unicode = NK_UTF_INVALID;
6342  *len = 0;
6343  return 0;
6344  }
6345 
6346  text = buffer;
6347  text_len = length;
6348  glyph_len = nk_utf_decode(text, unicode, text_len);
6349  while (glyph_len) {
6350  if (i == index) {
6351  *len = glyph_len;
6352  break;
6353  }
6354 
6355  i++;
6356  src_len = src_len + glyph_len;
6357  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
6358  }
6359  if (i != index) return 0;
6360  return buffer + src_len;
6361 }
6362 
6363 /* ==============================================================
6364  *
6365  * BUFFER
6366  *
6367  * ===============================================================*/
6368 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
6369 NK_INTERN void* nk_malloc(nk_handle unused, void *old,nk_size size)
6370 {NK_UNUSED(unused); NK_UNUSED(old); return malloc(size);}
6371 NK_INTERN void nk_mfree(nk_handle unused, void *ptr)
6372 {NK_UNUSED(unused); free(ptr);}
6373 
6374 NK_API void
6375 nk_buffer_init_default(struct nk_buffer *buffer)
6376 {
6377  struct nk_allocator alloc;
6378  alloc.userdata.ptr = 0;
6379  alloc.alloc = nk_malloc;
6380  alloc.free = nk_mfree;
6381  nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
6382 }
6383 #endif
6384 
6385 NK_API void
6386 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
6387  nk_size initial_size)
6388 {
6389  NK_ASSERT(b);
6390  NK_ASSERT(a);
6391  NK_ASSERT(initial_size);
6392  if (!b || !a || !initial_size) return;
6393 
6394  nk_zero(b, sizeof(*b));
6395  b->type = NK_BUFFER_DYNAMIC;
6396  b->memory.ptr = a->alloc(a->userdata,0, initial_size);
6397  b->memory.size = initial_size;
6398  b->size = initial_size;
6399  b->grow_factor = 2.0f;
6400  b->pool = *a;
6401 }
6402 
6403 NK_API void
6404 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
6405 {
6406  NK_ASSERT(b);
6407  NK_ASSERT(m);
6408  NK_ASSERT(size);
6409  if (!b || !m || !size) return;
6410 
6411  nk_zero(b, sizeof(*b));
6412  b->type = NK_BUFFER_FIXED;
6413  b->memory.ptr = m;
6414  b->memory.size = size;
6415  b->size = size;
6416 }
6417 
6418 NK_INTERN void*
6419 nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment,
6420  enum nk_buffer_allocation_type type)
6421 {
6422  void *memory = 0;
6423  switch (type) {
6424  default:
6425  case NK_BUFFER_MAX:
6426  case NK_BUFFER_FRONT:
6427  if (align) {
6428  memory = NK_ALIGN_PTR(unaligned, align);
6429  *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
6430  } else {
6431  memory = unaligned;
6432  *alignment = 0;
6433  }
6434  break;
6435  case NK_BUFFER_BACK:
6436  if (align) {
6437  memory = NK_ALIGN_PTR_BACK(unaligned, align);
6438  *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
6439  } else {
6440  memory = unaligned;
6441  *alignment = 0;
6442  }
6443  break;
6444  }
6445  return memory;
6446 }
6447 
6448 NK_INTERN void*
6449 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
6450 {
6451  void *temp;
6452  nk_size buffer_size;
6453 
6454  NK_ASSERT(b);
6455  NK_ASSERT(size);
6456  if (!b || !size || !b->pool.alloc || !b->pool.free)
6457  return 0;
6458 
6459  buffer_size = b->memory.size;
6460  temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
6461  NK_ASSERT(temp);
6462  if (!temp) return 0;
6463 
6464  *size = capacity;
6465  if (temp != b->memory.ptr) {
6466  NK_MEMCPY(temp, b->memory.ptr, buffer_size);
6467  b->pool.free(b->pool.userdata, b->memory.ptr);
6468  }
6469 
6470  if (b->size == buffer_size) {
6471  /* no back buffer so just set correct size */
6472  b->size = capacity;
6473  return temp;
6474  } else {
6475  /* copy back buffer to the end of the new buffer */
6476  void *dst, *src;
6477  nk_size back_size;
6478  back_size = buffer_size - b->size;
6479  dst = nk_ptr_add(void, temp, capacity - back_size);
6480  src = nk_ptr_add(void, temp, b->size);
6481  NK_MEMCPY(dst, src, back_size);
6482  b->size = capacity - back_size;
6483  }
6484  return temp;
6485 }
6486 
6487 NK_INTERN void*
6488 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
6489  nk_size size, nk_size align)
6490 {
6491  int full;
6492  nk_size alignment;
6493  void *unaligned;
6494  void *memory;
6495 
6496  NK_ASSERT(b);
6497  NK_ASSERT(size);
6498  if (!b || !size) return 0;
6499  b->needed += size;
6500 
6501  /* calculate total size with needed alignment + size */
6502  if (type == NK_BUFFER_FRONT)
6503  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
6504  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
6505  memory = nk_buffer_align(unaligned, align, &alignment, type);
6506 
6507  /* check if buffer has enough memory*/
6508  if (type == NK_BUFFER_FRONT)
6509  full = ((b->allocated + size + alignment) > b->size);
6510  else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
6511 
6512  if (full) {
6513  nk_size capacity;
6514  if (b->type != NK_BUFFER_DYNAMIC)
6515  return 0;
6516  NK_ASSERT(b->pool.alloc && b->pool.free);
6517  if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
6518  return 0;
6519 
6520  /* buffer is full so allocate bigger buffer if dynamic */
6521  capacity = (nk_size)((float)b->memory.size * b->grow_factor);
6522  capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
6523  b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
6524  if (!b->memory.ptr) return 0;
6525 
6526  /* align newly allocated pointer */
6527  if (type == NK_BUFFER_FRONT)
6528  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
6529  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
6530  memory = nk_buffer_align(unaligned, align, &alignment, type);
6531  }
6532 
6533  if (type == NK_BUFFER_FRONT)
6534  b->allocated += size + alignment;
6535  else b->size -= (size + alignment);
6536  b->needed += alignment;
6537  b->calls++;
6538  return memory;
6539 }
6540 
6541 NK_API void
6543  const void *memory, nk_size size, nk_size align)
6544 {
6545  void *mem = nk_buffer_alloc(b, type, size, align);
6546  if (!mem) return;
6547  NK_MEMCPY(mem, memory, size);
6548 }
6549 
6550 NK_API void
6551 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
6552 {
6553  NK_ASSERT(buffer);
6554  if (!buffer) return;
6555  buffer->marker[type].active = nk_true;
6556  if (type == NK_BUFFER_BACK)
6557  buffer->marker[type].offset = buffer->size;
6558  else buffer->marker[type].offset = buffer->allocated;
6559 }
6560 
6561 NK_API void
6562 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
6563 {
6564  NK_ASSERT(buffer);
6565  if (!buffer) return;
6566  if (type == NK_BUFFER_BACK) {
6567  /* reset back buffer either back to marker or empty */
6568  buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
6569  if (buffer->marker[type].active)
6570  buffer->size = buffer->marker[type].offset;
6571  else buffer->size = buffer->memory.size;
6572  buffer->marker[type].active = nk_false;
6573  } else {
6574  /* reset front buffer either back to back marker or empty */
6575  buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
6576  if (buffer->marker[type].active)
6577  buffer->allocated = buffer->marker[type].offset;
6578  else buffer->allocated = 0;
6579  buffer->marker[type].active = nk_false;
6580  }
6581 }
6582 
6583 NK_API void
6584 nk_buffer_clear(struct nk_buffer *b)
6585 {
6586  NK_ASSERT(b);
6587  if (!b) return;
6588  b->allocated = 0;
6589  b->size = b->memory.size;
6590  b->calls = 0;
6591  b->needed = 0;
6592 }
6593 
6594 NK_API void
6595 nk_buffer_free(struct nk_buffer *b)
6596 {
6597  NK_ASSERT(b);
6598  if (!b || !b->memory.ptr) return;
6599  if (b->type == NK_BUFFER_FIXED) return;
6600  if (!b->pool.free) return;
6601  NK_ASSERT(b->pool.free);
6602  b->pool.free(b->pool.userdata, b->memory.ptr);
6603 }
6604 
6605 NK_API void
6606 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
6607 {
6608  NK_ASSERT(b);
6609  NK_ASSERT(s);
6610  if (!s || !b) return;
6611  s->allocated = b->allocated;
6612  s->size = b->memory.size;
6613  s->needed = b->needed;
6614  s->memory = b->memory.ptr;
6615  s->calls = b->calls;
6616 }
6617 
6618 NK_API void*
6619 nk_buffer_memory(struct nk_buffer *buffer)
6620 {
6621  NK_ASSERT(buffer);
6622  if (!buffer) return 0;
6623  return buffer->memory.ptr;
6624 }
6625 
6626 NK_API const void*
6627 nk_buffer_memory_const(const struct nk_buffer *buffer)
6628 {
6629  NK_ASSERT(buffer);
6630  if (!buffer) return 0;
6631  return buffer->memory.ptr;
6632 }
6633 
6634 NK_API nk_size
6635 nk_buffer_total(struct nk_buffer *buffer)
6636 {
6637  NK_ASSERT(buffer);
6638  if (!buffer) return 0;
6639  return buffer->memory.size;
6640 }
6641 
6642 /*
6643  * ==============================================================
6644  *
6645  * STRING
6646  *
6647  * ===============================================================
6648  */
6649 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
6650 NK_API void
6651 nk_str_init_default(struct nk_str *str)
6652 {
6653  struct nk_allocator alloc;
6654  alloc.userdata.ptr = 0;
6655  alloc.alloc = nk_malloc;
6656  alloc.free = nk_mfree;
6657  nk_buffer_init(&str->buffer, &alloc, 32);
6658  str->len = 0;
6659 }
6660 #endif
6661 
6662 NK_API void
6663 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
6664 {
6665  nk_buffer_init(&str->buffer, alloc, size);
6666  str->len = 0;
6667 }
6668 
6669 NK_API void
6670 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
6671 {
6672  nk_buffer_init_fixed(&str->buffer, memory, size);
6673  str->len = 0;
6674 }
6675 
6676 NK_API int
6677 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
6678 {
6679  char *mem;
6680  NK_ASSERT(s);
6681  NK_ASSERT(str);
6682  if (!s || !str || !len) return 0;
6683  mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
6684  if (!mem) return 0;
6685  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
6686  s->len += nk_utf_len(str, len);
6687  return len;
6688 }
6689 
6690 NK_API int
6691 nk_str_append_str_char(struct nk_str *s, const char *str)
6692 {
6693  return nk_str_append_text_char(s, str, nk_strlen(str));
6694 }
6695 
6696 NK_API int
6697 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
6698 {
6699  int i = 0;
6700  int byte_len = 0;
6701  nk_rune unicode;
6702  if (!str || !text || !len) return 0;
6703  for (i = 0; i < len; ++i)
6704  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
6705  nk_str_append_text_char(str, text, byte_len);
6706  return len;
6707 }
6708 
6709 NK_API int
6710 nk_str_append_str_utf8(struct nk_str *str, const char *text)
6711 {
6712  int runes = 0;
6713  int byte_len = 0;
6714  int num_runes = 0;
6715  int glyph_len = 0;
6716  nk_rune unicode;
6717  if (!str || !text) return 0;
6718 
6719  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
6720  while (unicode != '\0' && glyph_len) {
6721  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
6722  byte_len += glyph_len;
6723  num_runes++;
6724  }
6725  nk_str_append_text_char(str, text, byte_len);
6726  return runes;
6727 }
6728 
6729 NK_API int
6730 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
6731 {
6732  int i = 0;
6733  int byte_len = 0;
6734  nk_glyph glyph;
6735 
6736  NK_ASSERT(str);
6737  if (!str || !text || !len) return 0;
6738  for (i = 0; i < len; ++i) {
6739  byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
6740  if (!byte_len) break;
6741  nk_str_append_text_char(str, glyph, byte_len);
6742  }
6743  return len;
6744 }
6745 
6746 NK_API int
6747 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
6748 {
6749  int i = 0;
6750  nk_glyph glyph;
6751  int byte_len;
6752  NK_ASSERT(str);
6753  if (!str || !runes) return 0;
6754  while (runes[i] != '\0') {
6755  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
6756  nk_str_append_text_char(str, glyph, byte_len);
6757  i++;
6758  }
6759  return i;
6760 }
6761 
6762 NK_API int
6763 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
6764 {
6765  int i;
6766  void *mem;
6767  char *src;
6768  char *dst;
6769 
6770  int copylen;
6771  NK_ASSERT(s);
6772  NK_ASSERT(str);
6773  NK_ASSERT(len >= 0);
6774  if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
6775  if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
6776  (s->buffer.type == NK_BUFFER_FIXED)) return 0;
6777 
6778  copylen = (int)s->buffer.allocated - pos;
6779  if (!copylen) {
6780  nk_str_append_text_char(s, str, len);
6781  return 1;
6782  }
6783  mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
6784  if (!mem) return 0;
6785 
6786  /* memmove */
6787  NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
6788  NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
6789  dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
6790  src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
6791  for (i = 0; i < copylen; ++i) *dst-- = *src--;
6792  mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
6793  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
6794  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
6795  return 1;
6796 }
6797 
6798 NK_API int
6799 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
6800 {
6801  int glyph_len;
6802  nk_rune unicode;
6803  const char *begin;
6804  const char *buffer;
6805 
6806  NK_ASSERT(str);
6807  NK_ASSERT(cstr);
6808  NK_ASSERT(len);
6809  if (!str || !cstr || !len) return 0;
6810  begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
6811  if (!str->len)
6812  return nk_str_append_text_char(str, cstr, len);
6813  buffer = nk_str_get_const(str);
6814  if (!begin) return 0;
6815  return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
6816 }
6817 
6818 NK_API int
6819 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
6820 {
6821  return nk_str_insert_text_utf8(str, pos, text, len);
6822 }
6823 
6824 NK_API int
6825 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
6826 {
6827  return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
6828 }
6829 
6830 NK_API int
6831 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
6832 {
6833  int i = 0;
6834  int byte_len = 0;
6835  nk_rune unicode;
6836 
6837  NK_ASSERT(str);
6838  NK_ASSERT(text);
6839  if (!str || !text || !len) return 0;
6840  for (i = 0; i < len; ++i)
6841  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
6842  nk_str_insert_at_rune(str, pos, text, byte_len);
6843  return len;
6844 }
6845 
6846 NK_API int
6847 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
6848 {
6849  int runes = 0;
6850  int byte_len = 0;
6851  int num_runes = 0;
6852  int glyph_len = 0;
6853  nk_rune unicode;
6854  if (!str || !text) return 0;
6855 
6856  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
6857  while (unicode != '\0' && glyph_len) {
6858  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
6859  byte_len += glyph_len;
6860  num_runes++;
6861  }
6862  nk_str_insert_at_rune(str, pos, text, byte_len);
6863  return runes;
6864 }
6865 
6866 NK_API int
6867 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
6868 {
6869  int i = 0;
6870  int byte_len = 0;
6871  nk_glyph glyph;
6872 
6873  NK_ASSERT(str);
6874  if (!str || !runes || !len) return 0;
6875  for (i = 0; i < len; ++i) {
6876  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
6877  if (!byte_len) break;
6878  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
6879  }
6880  return len;
6881 }
6882 
6883 NK_API int
6884 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
6885 {
6886  int i = 0;
6887  nk_glyph glyph;
6888  int byte_len;
6889  NK_ASSERT(str);
6890  if (!str || !runes) return 0;
6891  while (runes[i] != '\0') {
6892  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
6893  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
6894  i++;
6895  }
6896  return i;
6897 }
6898 
6899 NK_API void
6900 nk_str_remove_chars(struct nk_str *s, int len)
6901 {
6902  NK_ASSERT(s);
6903  NK_ASSERT(len >= 0);
6904  if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
6905  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
6906  s->buffer.allocated -= (nk_size)len;
6907  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
6908 }
6909 
6910 NK_API void
6911 nk_str_remove_runes(struct nk_str *str, int len)
6912 {
6913  int index;
6914  const char *begin;
6915  const char *end;
6916  nk_rune unicode;
6917 
6918  NK_ASSERT(str);
6919  NK_ASSERT(len >= 0);
6920  if (!str || len < 0) return;
6921  if (len >= str->len) {
6922  str->len = 0;
6923  return;
6924  }
6925 
6926  index = str->len - len;
6927  begin = nk_str_at_rune(str, index, &unicode, &len);
6928  end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
6929  nk_str_remove_chars(str, (int)(end-begin)+1);
6930 }
6931 
6932 NK_API void
6933 nk_str_delete_chars(struct nk_str *s, int pos, int len)
6934 {
6935  NK_ASSERT(s);
6936  if (!s || !len || (nk_size)pos > s->buffer.allocated ||
6937  (nk_size)(pos + len) > s->buffer.allocated) return;
6938 
6939  if ((nk_size)(pos + len) < s->buffer.allocated) {
6940  /* memmove */
6941  char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
6942  char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
6943  NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
6944  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
6945  s->buffer.allocated -= (nk_size)len;
6946  } else nk_str_remove_chars(s, len);
6947  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
6948 }
6949 
6950 NK_API void
6951 nk_str_delete_runes(struct nk_str *s, int pos, int len)
6952 {
6953  char *temp;
6954  nk_rune unicode;
6955  char *begin;
6956  char *end;
6957  int unused;
6958 
6959  NK_ASSERT(s);
6960  NK_ASSERT(s->len >= pos + len);
6961  if (s->len < pos + len)
6962  len = NK_CLAMP(0, (s->len - pos), s->len);
6963  if (!len) return;
6964 
6965  temp = (char *)s->buffer.memory.ptr;
6966  begin = nk_str_at_rune(s, pos, &unicode, &unused);
6967  if (!begin) return;
6968  s->buffer.memory.ptr = begin;
6969  end = nk_str_at_rune(s, len, &unicode, &unused);
6970  s->buffer.memory.ptr = temp;
6971  if (!end) return;
6972  nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
6973 }
6974 
6975 NK_API char*
6976 nk_str_at_char(struct nk_str *s, int pos)
6977 {
6978  NK_ASSERT(s);
6979  if (!s || pos > (int)s->buffer.allocated) return 0;
6980  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
6981 }
6982 
6983 NK_API char*
6984 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
6985 {
6986  int i = 0;
6987  int src_len = 0;
6988  int glyph_len = 0;
6989  char *text;
6990  int text_len;
6991 
6992  NK_ASSERT(str);
6993  NK_ASSERT(unicode);
6994  NK_ASSERT(len);
6995 
6996  if (!str || !unicode || !len) return 0;
6997  if (pos < 0) {
6998  *unicode = 0;
6999  *len = 0;
7000  return 0;
7001  }
7002 
7003  text = (char*)str->buffer.memory.ptr;
7004  text_len = (int)str->buffer.allocated;
7005  glyph_len = nk_utf_decode(text, unicode, text_len);
7006  while (glyph_len) {
7007  if (i == pos) {
7008  *len = glyph_len;
7009  break;
7010  }
7011 
7012  i++;
7013  src_len = src_len + glyph_len;
7014  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7015  }
7016  if (i != pos) return 0;
7017  return text + src_len;
7018 }
7019 
7020 NK_API const char*
7021 nk_str_at_char_const(const struct nk_str *s, int pos)
7022 {
7023  NK_ASSERT(s);
7024  if (!s || pos > (int)s->buffer.allocated) return 0;
7025  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
7026 }
7027 
7028 NK_API const char*
7029 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
7030 {
7031  int i = 0;
7032  int src_len = 0;
7033  int glyph_len = 0;
7034  char *text;
7035  int text_len;
7036 
7037  NK_ASSERT(str);
7038  NK_ASSERT(unicode);
7039  NK_ASSERT(len);
7040 
7041  if (!str || !unicode || !len) return 0;
7042  if (pos < 0) {
7043  *unicode = 0;
7044  *len = 0;
7045  return 0;
7046  }
7047 
7048  text = (char*)str->buffer.memory.ptr;
7049  text_len = (int)str->buffer.allocated;
7050  glyph_len = nk_utf_decode(text, unicode, text_len);
7051  while (glyph_len) {
7052  if (i == pos) {
7053  *len = glyph_len;
7054  break;
7055  }
7056 
7057  i++;
7058  src_len = src_len + glyph_len;
7059  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7060  }
7061  if (i != pos) return 0;
7062  return text + src_len;
7063 }
7064 
7065 NK_API nk_rune
7066 nk_str_rune_at(const struct nk_str *str, int pos)
7067 {
7068  int len;
7069  nk_rune unicode = 0;
7070  nk_str_at_const(str, pos, &unicode, &len);
7071  return unicode;
7072 }
7073 
7074 NK_API char*
7075 nk_str_get(struct nk_str *s)
7076 {
7077  NK_ASSERT(s);
7078  if (!s || !s->len || !s->buffer.allocated) return 0;
7079  return (char*)s->buffer.memory.ptr;
7080 }
7081 
7082 NK_API const char*
7083 nk_str_get_const(const struct nk_str *s)
7084 {
7085  NK_ASSERT(s);
7086  if (!s || !s->len || !s->buffer.allocated) return 0;
7087  return (const char*)s->buffer.memory.ptr;
7088 }
7089 
7090 NK_API int
7091 nk_str_len(struct nk_str *s)
7092 {
7093  NK_ASSERT(s);
7094  if (!s || !s->len || !s->buffer.allocated) return 0;
7095  return s->len;
7096 }
7097 
7098 NK_API int
7099 nk_str_len_char(struct nk_str *s)
7100 {
7101  NK_ASSERT(s);
7102  if (!s || !s->len || !s->buffer.allocated) return 0;
7103  return (int)s->buffer.allocated;
7104 }
7105 
7106 NK_API void
7107 nk_str_clear(struct nk_str *str)
7108 {
7109  NK_ASSERT(str);
7110  nk_buffer_clear(&str->buffer);
7111  str->len = 0;
7112 }
7113 
7114 NK_API void
7115 nk_str_free(struct nk_str *str)
7116 {
7117  NK_ASSERT(str);
7118  nk_buffer_free(&str->buffer);
7119  str->len = 0;
7120 }
7121 
7122 /*
7123  * ==============================================================
7124  *
7125  * Command buffer
7126  *
7127  * ===============================================================
7128 */
7129 NK_INTERN void
7130 nk_command_buffer_init(struct nk_command_buffer *cmdbuf,
7131  struct nk_buffer *buffer, enum nk_command_clipping clip)
7132 {
7133  NK_ASSERT(cmdbuf);
7134  NK_ASSERT(buffer);
7135  if (!cmdbuf || !buffer) return;
7136  cmdbuf->base = buffer;
7137  cmdbuf->use_clipping = clip;
7138  cmdbuf->begin = buffer->allocated;
7139  cmdbuf->end = buffer->allocated;
7140  cmdbuf->last = buffer->allocated;
7141 }
7142 
7143 NK_INTERN void
7144 nk_command_buffer_reset(struct nk_command_buffer *buffer)
7145 {
7146  NK_ASSERT(buffer);
7147  if (!buffer) return;
7148  buffer->begin = 0;
7149  buffer->end = 0;
7150  buffer->last = 0;
7151  buffer->clip = nk_null_rect;
7152 #ifdef NK_INCLUDE_COMMAND_USERDATA
7153  buffer->userdata.ptr = 0;
7154 #endif
7155 }
7156 
7157 NK_INTERN void*
7158 nk_command_buffer_push(struct nk_command_buffer* b,
7159  enum nk_command_type t, nk_size size)
7160 {
7161  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
7162  struct nk_command *cmd;
7163  nk_size alignment;
7164  void *unaligned;
7165  void *memory;
7166 
7167  NK_ASSERT(b);
7168  NK_ASSERT(b->base);
7169  if (!b) return 0;
7170  cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
7171  if (!cmd) return 0;
7172 
7173  /* make sure the offset to the next command is aligned */
7174  b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
7175  unaligned = (nk_byte*)cmd + size;
7176  memory = NK_ALIGN_PTR(unaligned, align);
7177  alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
7178 #ifdef NK_ZERO_COMMAND_MEMORY
7179  NK_MEMSET(cmd, 0, size + alignment);
7180 #endif
7181 
7182  cmd->type = t;
7183  cmd->next = b->base->allocated + alignment;
7184 #ifdef NK_INCLUDE_COMMAND_USERDATA
7185  cmd->userdata = b->userdata;
7186 #endif
7187  b->end = cmd->next;
7188  return cmd;
7189 }
7190 
7191 NK_API void
7192 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
7193 {
7194  struct nk_command_scissor *cmd;
7195  NK_ASSERT(b);
7196  if (!b) return;
7197 
7198  b->clip.x = r.x;
7199  b->clip.y = r.y;
7200  b->clip.w = r.w;
7201  b->clip.h = r.h;
7202  cmd = (struct nk_command_scissor*)
7203  nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
7204 
7205  if (!cmd) return;
7206  cmd->x = (short)r.x;
7207  cmd->y = (short)r.y;
7208  cmd->w = (unsigned short)NK_MAX(0, r.w);
7209  cmd->h = (unsigned short)NK_MAX(0, r.h);
7210 }
7211 
7212 NK_API void
7213 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
7214  float x1, float y1, float line_thickness, struct nk_color c)
7215 {
7216  struct nk_command_line *cmd;
7217  NK_ASSERT(b);
7218  if (!b) return;
7219  cmd = (struct nk_command_line*)
7220  nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
7221  if (!cmd) return;
7222  cmd->line_thickness = (unsigned short)line_thickness;
7223  cmd->begin.x = (short)x0;
7224  cmd->begin.y = (short)y0;
7225  cmd->end.x = (short)x1;
7226  cmd->end.y = (short)y1;
7227  cmd->color = c;
7228 }
7229 
7230 NK_API void
7231 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
7232  float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
7233  float bx, float by, float line_thickness, struct nk_color col)
7234 {
7235  struct nk_command_curve *cmd;
7236  NK_ASSERT(b);
7237  if (!b || col.a == 0) return;
7238 
7239  cmd = (struct nk_command_curve*)
7240  nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
7241  if (!cmd) return;
7242  cmd->line_thickness = (unsigned short)line_thickness;
7243  cmd->begin.x = (short)ax;
7244  cmd->begin.y = (short)ay;
7245  cmd->ctrl[0].x = (short)ctrl0x;
7246  cmd->ctrl[0].y = (short)ctrl0y;
7247  cmd->ctrl[1].x = (short)ctrl1x;
7248  cmd->ctrl[1].y = (short)ctrl1y;
7249  cmd->end.x = (short)bx;
7250  cmd->end.y = (short)by;
7251  cmd->color = col;
7252 }
7253 
7254 NK_API void
7255 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
7256  float rounding, float line_thickness, struct nk_color c)
7257 {
7258  struct nk_command_rect *cmd;
7259  NK_ASSERT(b);
7260  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
7261  if (b->use_clipping) {
7262  const struct nk_rect *clip = &b->clip;
7263  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7264  clip->x, clip->y, clip->w, clip->h)) return;
7265  }
7266 
7267  cmd = (struct nk_command_rect*)
7268  nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
7269  if (!cmd) return;
7270  cmd->rounding = (unsigned short)rounding;
7271  cmd->line_thickness = (unsigned short)line_thickness;
7272  cmd->x = (short)rect.x;
7273  cmd->y = (short)rect.y;
7274  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7275  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7276  cmd->color = c;
7277 }
7278 
7279 NK_API void
7280 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
7281  float rounding, struct nk_color c)
7282 {
7283  struct nk_command_rect_filled *cmd;
7284  NK_ASSERT(b);
7285  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
7286  if (b->use_clipping) {
7287  const struct nk_rect *clip = &b->clip;
7288  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7289  clip->x, clip->y, clip->w, clip->h)) return;
7290  }
7291 
7292  cmd = (struct nk_command_rect_filled*)
7293  nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
7294  if (!cmd) return;
7295  cmd->rounding = (unsigned short)rounding;
7296  cmd->x = (short)rect.x;
7297  cmd->y = (short)rect.y;
7298  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7299  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7300  cmd->color = c;
7301 }
7302 
7303 NK_API void
7304 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect,
7305  struct nk_color left, struct nk_color top, struct nk_color right,
7306  struct nk_color bottom)
7307 {
7308  struct nk_command_rect_multi_color *cmd;
7309  NK_ASSERT(b);
7310  if (!b || rect.w == 0 || rect.h == 0) return;
7311  if (b->use_clipping) {
7312  const struct nk_rect *clip = &b->clip;
7313  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7314  clip->x, clip->y, clip->w, clip->h)) return;
7315  }
7316 
7317  cmd = (struct nk_command_rect_multi_color*)
7318  nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
7319  if (!cmd) return;
7320  cmd->x = (short)rect.x;
7321  cmd->y = (short)rect.y;
7322  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7323  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7324  cmd->left = left;
7325  cmd->top = top;
7326  cmd->right = right;
7327  cmd->bottom = bottom;
7328 }
7329 
7330 NK_API void
7331 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
7332  float line_thickness, struct nk_color c)
7333 {
7334  struct nk_command_circle *cmd;
7335  if (!b || r.w == 0 || r.h == 0) return;
7336  if (b->use_clipping) {
7337  const struct nk_rect *clip = &b->clip;
7338  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
7339  return;
7340  }
7341 
7342  cmd = (struct nk_command_circle*)
7343  nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
7344  if (!cmd) return;
7345  cmd->line_thickness = (unsigned short)line_thickness;
7346  cmd->x = (short)r.x;
7347  cmd->y = (short)r.y;
7348  cmd->w = (unsigned short)NK_MAX(r.w, 0);
7349  cmd->h = (unsigned short)NK_MAX(r.h, 0);
7350  cmd->color = c;
7351 }
7352 
7353 NK_API void
7354 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
7355 {
7356  struct nk_command_circle_filled *cmd;
7357  NK_ASSERT(b);
7358  if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
7359  if (b->use_clipping) {
7360  const struct nk_rect *clip = &b->clip;
7361  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
7362  return;
7363  }
7364 
7365  cmd = (struct nk_command_circle_filled*)
7366  nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
7367  if (!cmd) return;
7368  cmd->x = (short)r.x;
7369  cmd->y = (short)r.y;
7370  cmd->w = (unsigned short)NK_MAX(r.w, 0);
7371  cmd->h = (unsigned short)NK_MAX(r.h, 0);
7372  cmd->color = c;
7373 }
7374 
7375 NK_API void
7376 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
7377  float a_min, float a_max, float line_thickness, struct nk_color c)
7378 {
7379  struct nk_command_arc *cmd;
7380  if (!b || c.a == 0) return;
7381  cmd = (struct nk_command_arc*)
7382  nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
7383  if (!cmd) return;
7384  cmd->line_thickness = (unsigned short)line_thickness;
7385  cmd->cx = (short)cx;
7386  cmd->cy = (short)cy;
7387  cmd->r = (unsigned short)radius;
7388  cmd->a[0] = a_min;
7389  cmd->a[1] = a_max;
7390  cmd->color = c;
7391 }
7392 
7393 NK_API void
7394 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
7395  float a_min, float a_max, struct nk_color c)
7396 {
7397  struct nk_command_arc_filled *cmd;
7398  NK_ASSERT(b);
7399  if (!b || c.a == 0) return;
7400  cmd = (struct nk_command_arc_filled*)
7401  nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
7402  if (!cmd) return;
7403  cmd->cx = (short)cx;
7404  cmd->cy = (short)cy;
7405  cmd->r = (unsigned short)radius;
7406  cmd->a[0] = a_min;
7407  cmd->a[1] = a_max;
7408  cmd->color = c;
7409 }
7410 
7411 NK_API void
7412 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
7413  float y1, float x2, float y2, float line_thickness, struct nk_color c)
7414 {
7415  struct nk_command_triangle *cmd;
7416  NK_ASSERT(b);
7417  if (!b || c.a == 0) return;
7418  if (b->use_clipping) {
7419  const struct nk_rect *clip = &b->clip;
7420  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
7421  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
7422  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
7423  return;
7424  }
7425 
7426  cmd = (struct nk_command_triangle*)
7427  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
7428  if (!cmd) return;
7429  cmd->line_thickness = (unsigned short)line_thickness;
7430  cmd->a.x = (short)x0;
7431  cmd->a.y = (short)y0;
7432  cmd->b.x = (short)x1;
7433  cmd->b.y = (short)y1;
7434  cmd->c.x = (short)x2;
7435  cmd->c.y = (short)y2;
7436  cmd->color = c;
7437 }
7438 
7439 NK_API void
7440 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
7441  float y1, float x2, float y2, struct nk_color c)
7442 {
7443  struct nk_command_triangle_filled *cmd;
7444  NK_ASSERT(b);
7445  if (!b || c.a == 0) return;
7446  if (!b) return;
7447  if (b->use_clipping) {
7448  const struct nk_rect *clip = &b->clip;
7449  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
7450  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
7451  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
7452  return;
7453  }
7454 
7455  cmd = (struct nk_command_triangle_filled*)
7456  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
7457  if (!cmd) return;
7458  cmd->a.x = (short)x0;
7459  cmd->a.y = (short)y0;
7460  cmd->b.x = (short)x1;
7461  cmd->b.y = (short)y1;
7462  cmd->c.x = (short)x2;
7463  cmd->c.y = (short)y2;
7464  cmd->color = c;
7465 }
7466 
7467 NK_API void
7468 nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count,
7469  float line_thickness, struct nk_color col)
7470 {
7471  int i;
7472  nk_size size = 0;
7473  struct nk_command_polygon *cmd;
7474 
7475  NK_ASSERT(b);
7476  if (!b || col.a == 0) return;
7477  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7478  cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
7479  if (!cmd) return;
7480  cmd->color = col;
7481  cmd->line_thickness = (unsigned short)line_thickness;
7482  cmd->point_count = (unsigned short)point_count;
7483  for (i = 0; i < point_count; ++i) {
7484  cmd->points[i].x = (short)points[i*2];
7485  cmd->points[i].y = (short)points[i*2+1];
7486  }
7487 }
7488 
7489 NK_API void
7490 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count,
7491  struct nk_color col)
7492 {
7493  int i;
7494  nk_size size = 0;
7495  struct nk_command_polygon_filled *cmd;
7496 
7497  NK_ASSERT(b);
7498  if (!b || col.a == 0) return;
7499  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7500  cmd = (struct nk_command_polygon_filled*)
7501  nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
7502  if (!cmd) return;
7503  cmd->color = col;
7504  cmd->point_count = (unsigned short)point_count;
7505  for (i = 0; i < point_count; ++i) {
7506  cmd->points[i].x = (short)points[i*2+0];
7507  cmd->points[i].y = (short)points[i*2+1];
7508  }
7509 }
7510 
7511 NK_API void
7512 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count,
7513  float line_thickness, struct nk_color col)
7514 {
7515  int i;
7516  nk_size size = 0;
7517  struct nk_command_polyline *cmd;
7518 
7519  NK_ASSERT(b);
7520  if (!b || col.a == 0) return;
7521  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7522  cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
7523  if (!cmd) return;
7524  cmd->color = col;
7525  cmd->point_count = (unsigned short)point_count;
7526  cmd->line_thickness = (unsigned short)line_thickness;
7527  for (i = 0; i < point_count; ++i) {
7528  cmd->points[i].x = (short)points[i*2];
7529  cmd->points[i].y = (short)points[i*2+1];
7530  }
7531 }
7532 
7533 NK_API void
7534 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
7535  const struct nk_image *img, struct nk_color col)
7536 {
7537  struct nk_command_image *cmd;
7538  NK_ASSERT(b);
7539  if (!b) return;
7540  if (b->use_clipping) {
7541  const struct nk_rect *c = &b->clip;
7542  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
7543  return;
7544  }
7545 
7546  cmd = (struct nk_command_image*)
7547  nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
7548  if (!cmd) return;
7549  cmd->x = (short)r.x;
7550  cmd->y = (short)r.y;
7551  cmd->w = (unsigned short)NK_MAX(0, r.w);
7552  cmd->h = (unsigned short)NK_MAX(0, r.h);
7553  cmd->img = *img;
7554  cmd->col = col;
7555 }
7556 
7557 NK_API void
7558 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
7559  nk_command_custom_callback cb, nk_handle usr)
7560 {
7561  struct nk_command_custom *cmd;
7562  NK_ASSERT(b);
7563  if (!b) return;
7564  if (b->use_clipping) {
7565  const struct nk_rect *c = &b->clip;
7566  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
7567  return;
7568  }
7569 
7570  cmd = (struct nk_command_custom*)
7571  nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
7572  if (!cmd) return;
7573  cmd->x = (short)r.x;
7574  cmd->y = (short)r.y;
7575  cmd->w = (unsigned short)NK_MAX(0, r.w);
7576  cmd->h = (unsigned short)NK_MAX(0, r.h);
7577  cmd->callback_data = usr;
7578  cmd->callback = cb;
7579 }
7580 
7581 NK_API void
7582 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
7583  const char *string, int length, const struct nk_user_font *font,
7584  struct nk_color bg, struct nk_color fg)
7585 {
7586  float text_width = 0;
7587  struct nk_command_text *cmd;
7588 
7589  NK_ASSERT(b);
7590  NK_ASSERT(font);
7591  if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
7592  if (b->use_clipping) {
7593  const struct nk_rect *c = &b->clip;
7594  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
7595  return;
7596  }
7597 
7598  /* make sure text fits inside bounds */
7599  text_width = font->width(font->userdata, font->height, string, length);
7600  if (text_width > r.w){
7601  int glyphs = 0;
7602  float txt_width = (float)text_width;
7603  length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
7604  }
7605 
7606  if (!length) return;
7607  cmd = (struct nk_command_text*)
7608  nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
7609  if (!cmd) return;
7610  cmd->x = (short)r.x;
7611  cmd->y = (short)r.y;
7612  cmd->w = (unsigned short)r.w;
7613  cmd->h = (unsigned short)r.h;
7614  cmd->background = bg;
7615  cmd->foreground = fg;
7616  cmd->font = font;
7617  cmd->length = length;
7618  cmd->height = font->height;
7619  NK_MEMCPY(cmd->string, string, (nk_size)length);
7620  cmd->string[length] = '\0';
7621 }
7622 
7623 /* ==============================================================
7624  *
7625  * DRAW LIST
7626  *
7627  * ===============================================================*/
7628 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
7629 NK_API void
7630 nk_draw_list_init(struct nk_draw_list *list)
7631 {
7632  nk_size i = 0;
7633  NK_ASSERT(list);
7634  if (!list) return;
7635  nk_zero(list, sizeof(*list));
7636  for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
7637  const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
7638  list->circle_vtx[i].x = (float)NK_COS(a);
7639  list->circle_vtx[i].y = (float)NK_SIN(a);
7640  }
7641 }
7642 
7643 NK_API void
7644 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
7645  struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements)
7646 {
7647  NK_ASSERT(canvas);
7648  NK_ASSERT(config);
7649  NK_ASSERT(cmds);
7650  NK_ASSERT(vertices);
7651  NK_ASSERT(elements);
7652  if (!canvas || !config || !cmds || !vertices || !elements)
7653  return;
7654 
7655  canvas->buffer = cmds;
7656  canvas->config = *config;
7657  canvas->elements = elements;
7658  canvas->vertices = vertices;
7659  canvas->clip_rect = nk_null_rect;
7660 }
7661 
7662 NK_API const struct nk_draw_command*
7663 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
7664 {
7665  nk_byte *memory;
7666  nk_size offset;
7667  const struct nk_draw_command *cmd;
7668 
7669  NK_ASSERT(buffer);
7670  if (!buffer || !buffer->size || !canvas->cmd_count)
7671  return 0;
7672 
7673  memory = (nk_byte*)buffer->memory.ptr;
7674  offset = buffer->memory.size - canvas->cmd_offset;
7675  cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
7676  return cmd;
7677 }
7678 
7679 NK_API const struct nk_draw_command*
7680 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
7681 {
7682  nk_size size;
7683  nk_size offset;
7684  nk_byte *memory;
7685  const struct nk_draw_command *end;
7686 
7687  NK_ASSERT(buffer);
7688  NK_ASSERT(canvas);
7689  if (!buffer || !canvas)
7690  return 0;
7691 
7692  memory = (nk_byte*)buffer->memory.ptr;
7693  size = buffer->memory.size;
7694  offset = size - canvas->cmd_offset;
7695  end = nk_ptr_add(const struct nk_draw_command, memory, offset);
7696  end -= (canvas->cmd_count-1);
7697  return end;
7698 }
7699 
7700 NK_API const struct nk_draw_command*
7701 nk__draw_list_next(const struct nk_draw_command *cmd,
7702  const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
7703 {
7704  const struct nk_draw_command *end;
7705  NK_ASSERT(buffer);
7706  NK_ASSERT(canvas);
7707  if (!cmd || !buffer || !canvas)
7708  return 0;
7709 
7710  end = nk__draw_list_end(canvas, buffer);
7711  if (cmd <= end) return 0;
7712  return (cmd-1);
7713 }
7714 
7715 NK_API void
7716 nk_draw_list_clear(struct nk_draw_list *list)
7717 {
7718  NK_ASSERT(list);
7719  if (!list) return;
7720  if (list->buffer)
7721  nk_buffer_clear(list->buffer);
7722  if (list->vertices)
7723  nk_buffer_clear(list->vertices);
7724  if (list->elements)
7725  nk_buffer_clear(list->elements);
7726 
7727  list->element_count = 0;
7728  list->vertex_count = 0;
7729  list->cmd_offset = 0;
7730  list->cmd_count = 0;
7731  list->path_count = 0;
7732  list->vertices = 0;
7733  list->elements = 0;
7734  list->clip_rect = nk_null_rect;
7735 }
7736 
7737 NK_INTERN struct nk_vec2*
7738 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
7739 {
7740  struct nk_vec2 *points;
7741  NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
7742  NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
7743  points = (struct nk_vec2*)
7744  nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
7745  point_size * (nk_size)count, point_align);
7746 
7747  if (!points) return 0;
7748  if (!list->path_offset) {
7749  void *memory = nk_buffer_memory(list->buffer);
7750  list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
7751  }
7752  list->path_count += (unsigned int)count;
7753  return points;
7754 }
7755 
7756 NK_INTERN struct nk_vec2
7757 nk_draw_list_path_last(struct nk_draw_list *list)
7758 {
7759  void *memory;
7760  struct nk_vec2 *point;
7761  NK_ASSERT(list->path_count);
7762  memory = nk_buffer_memory(list->buffer);
7763  point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
7764  point += (list->path_count-1);
7765  return *point;
7766 }
7767 
7768 NK_INTERN struct nk_draw_command*
7769 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
7770  nk_handle texture)
7771 {
7772  NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
7773  NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
7774  struct nk_draw_command *cmd;
7775 
7776  NK_ASSERT(list);
7777  cmd = (struct nk_draw_command*)
7778  nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
7779 
7780  if (!cmd) return 0;
7781  if (!list->cmd_count) {
7782  nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
7783  nk_size total = nk_buffer_total(list->buffer);
7784  memory = nk_ptr_add(nk_byte, memory, total);
7785  list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
7786  }
7787 
7788  cmd->elem_count = 0;
7789  cmd->clip_rect = clip;
7790  cmd->texture = texture;
7791 #ifdef NK_INCLUDE_COMMAND_USERDATA
7792  cmd->userdata = list->userdata;
7793 #endif
7794 
7795  list->cmd_count++;
7796  list->clip_rect = clip;
7797  return cmd;
7798 }
7799 
7800 NK_INTERN struct nk_draw_command*
7801 nk_draw_list_command_last(struct nk_draw_list *list)
7802 {
7803  void *memory;
7804  nk_size size;
7805  struct nk_draw_command *cmd;
7806  NK_ASSERT(list->cmd_count);
7807 
7808  memory = nk_buffer_memory(list->buffer);
7809  size = nk_buffer_total(list->buffer);
7810  cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
7811  return (cmd - (list->cmd_count-1));
7812 }
7813 
7814 NK_INTERN void
7815 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
7816 {
7817  NK_ASSERT(list);
7818  if (!list) return;
7819  if (!list->cmd_count) {
7820  nk_draw_list_push_command(list, rect, list->config.null.texture);
7821  } else {
7822  struct nk_draw_command *prev = nk_draw_list_command_last(list);
7823  if (prev->elem_count == 0)
7824  prev->clip_rect = rect;
7825  nk_draw_list_push_command(list, rect, prev->texture);
7826  }
7827 }
7828 
7829 NK_INTERN void
7830 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
7831 {
7832  NK_ASSERT(list);
7833  if (!list) return;
7834  if (!list->cmd_count) {
7835  nk_draw_list_push_command(list, nk_null_rect, texture);
7836  } else {
7837  struct nk_draw_command *prev = nk_draw_list_command_last(list);
7838  if (prev->elem_count == 0)
7839  prev->texture = texture;
7840  else if (prev->texture.id != texture.id)
7841  nk_draw_list_push_command(list, prev->clip_rect, texture);
7842  }
7843 }
7844 
7845 #ifdef NK_INCLUDE_COMMAND_USERDATA
7846 NK_API void
7847 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
7848 {
7849  list->userdata = userdata;
7850 }
7851 #endif
7852 
7853 NK_INTERN void*
7854 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
7855 {
7856  void *vtx;
7857  NK_ASSERT(list);
7858  if (!list) return 0;
7859  vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
7860  list->config.vertex_size*count, list->config.vertex_alignment);
7861  if (!vtx) return 0;
7862  list->vertex_count += (unsigned int)count;
7863  return vtx;
7864 }
7865 
7866 NK_INTERN nk_draw_index*
7867 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
7868 {
7869  nk_draw_index *ids;
7870  struct nk_draw_command *cmd;
7871  NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
7872  NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
7873  NK_ASSERT(list);
7874  if (!list) return 0;
7875 
7876  ids = (nk_draw_index*)
7877  nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
7878  if (!ids) return 0;
7879  cmd = nk_draw_list_command_last(list);
7880  list->element_count += (unsigned int)count;
7881  cmd->elem_count += (unsigned int)count;
7882  return ids;
7883 }
7884 
7885 NK_INTERN int
7886 nk_draw_vertex_layout_element_is_end_of_layout(
7887  const struct nk_draw_vertex_layout_element *element)
7888 {
7889  return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
7890  element->format == NK_FORMAT_COUNT);
7891 }
7892 
7893 NK_INTERN void
7894 nk_draw_vertex_color(void *attribute, const float *values,
7895  enum nk_draw_vertex_layout_format format)
7896 {
7897  /* if this triggers you tried to provide a value format for a color */
7898  NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
7899  NK_ASSERT(format <= NK_FORMAT_COLOR_END);
7900  if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
7901 
7902  switch (format) {
7903  default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
7904  case NK_FORMAT_R8G8B8A8:
7905  case NK_FORMAT_R8G8B8: {
7906  struct nk_color col = nk_rgba_fv(values);
7907  NK_MEMCPY(attribute, &col.r, sizeof(col));
7908  } break;
7909  case NK_FORMAT_R16G15B16: {
7910  nk_ushort col[3];
7911  col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);
7912  col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX);
7913  col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX);
7914  NK_MEMCPY(attribute, col, sizeof(col));
7915  } break;
7916  case NK_FORMAT_R16G15B16A16: {
7917  nk_ushort col[4];
7918  col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);
7919  col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX);
7920  col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX);
7921  col[3] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[3] * NK_USHORT_MAX, NK_USHORT_MAX);
7922  NK_MEMCPY(attribute, col, sizeof(col));
7923  } break;
7924  case NK_FORMAT_R32G32B32: {
7925  nk_uint col[3];
7926  col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX);
7927  col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX);
7928  col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX);
7929  NK_MEMCPY(attribute, col, sizeof(col));
7930  } break;
7931  case NK_FORMAT_R32G32B32A32: {
7932  nk_uint col[4];
7933  col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX);
7934  col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX);
7935  col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX);
7936  col[3] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[3] * NK_UINT_MAX, NK_UINT_MAX);
7937  NK_MEMCPY(attribute, col, sizeof(col));
7938  } break;
7939  case NK_FORMAT_R32G32B32A32_FLOAT:
7940  NK_MEMCPY(attribute, values, sizeof(float)*4);
7941  break;
7942  case NK_FORMAT_R32G32B32A32_DOUBLE: {
7943  double col[4];
7944  col[0] = (double)NK_SATURATE(values[0]);
7945  col[1] = (double)NK_SATURATE(values[1]);
7946  col[2] = (double)NK_SATURATE(values[2]);
7947  col[3] = (double)NK_SATURATE(values[3]);
7948  NK_MEMCPY(attribute, col, sizeof(col));
7949  } break;
7950  case NK_FORMAT_RGB32:
7951  case NK_FORMAT_RGBA32: {
7952  struct nk_color col = nk_rgba_fv(values);
7953  nk_uint color = nk_color_u32(col);
7954  NK_MEMCPY(attribute, &color, sizeof(color));
7955  } break;
7956  }
7957 }
7958 
7959 NK_INTERN void
7960 nk_draw_vertex_element(void *dst, const float *values, int value_count,
7961  enum nk_draw_vertex_layout_format format)
7962 {
7963  int value_index;
7964  void *attribute = dst;
7965  /* if this triggers you tried to provide a color format for a value */
7966  NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
7967  if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
7968  for (value_index = 0; value_index < value_count; ++value_index) {
7969  switch (format) {
7970  default: NK_ASSERT(0 && "invalid vertex layout format"); break;
7971  case NK_FORMAT_SCHAR: {
7972  char value = (char)NK_CLAMP(NK_SCHAR_MIN, values[value_index], NK_SCHAR_MAX);
7973  NK_MEMCPY(attribute, &value, sizeof(value));
7974  attribute = (void*)((char*)attribute + sizeof(char));
7975  } break;
7976  case NK_FORMAT_SSHORT: {
7977  nk_short value = (nk_short)NK_CLAMP(NK_SSHORT_MIN, values[value_index], NK_SSHORT_MAX);
7978  NK_MEMCPY(attribute, &value, sizeof(value));
7979  attribute = (void*)((char*)attribute + sizeof(value));
7980  } break;
7981  case NK_FORMAT_SINT: {
7982  nk_int value = (nk_int)NK_CLAMP(NK_SINT_MIN, values[value_index], NK_SINT_MAX);
7983  NK_MEMCPY(attribute, &value, sizeof(value));
7984  attribute = (void*)((char*)attribute + sizeof(nk_int));
7985  } break;
7986  case NK_FORMAT_UCHAR: {
7987  unsigned char value = (unsigned char)NK_CLAMP(NK_UCHAR_MIN, values[value_index], NK_UCHAR_MAX);
7988  NK_MEMCPY(attribute, &value, sizeof(value));
7989  attribute = (void*)((char*)attribute + sizeof(unsigned char));
7990  } break;
7991  case NK_FORMAT_USHORT: {
7992  nk_ushort value = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[value_index], NK_USHORT_MAX);
7993  NK_MEMCPY(attribute, &value, sizeof(value));
7994  attribute = (void*)((char*)attribute + sizeof(value));
7995  } break;
7996  case NK_FORMAT_UINT: {
7997  nk_uint value = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[value_index], NK_UINT_MAX);
7998  NK_MEMCPY(attribute, &value, sizeof(value));
7999  attribute = (void*)((char*)attribute + sizeof(nk_uint));
8000  } break;
8001  case NK_FORMAT_FLOAT:
8002  NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
8003  attribute = (void*)((char*)attribute + sizeof(float));
8004  break;
8005  case NK_FORMAT_DOUBLE: {
8006  double value = (double)values[value_index];
8007  NK_MEMCPY(attribute, &value, sizeof(value));
8008  attribute = (void*)((char*)attribute + sizeof(double));
8009  } break;
8010  }
8011  }
8012 }
8013 
8014 NK_INTERN void*
8015 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
8016  struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
8017 {
8018  void *result = (void*)((char*)dst + config->vertex_size);
8019  const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
8020  while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
8021  void *address = (void*)((char*)dst + elem_iter->offset);
8022  switch (elem_iter->attribute) {
8023  case NK_VERTEX_ATTRIBUTE_COUNT:
8024  default: NK_ASSERT(0 && "wrong element attribute");
8025  case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
8026  case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
8027  case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
8028  }
8029  elem_iter++;
8030  }
8031  return result;
8032 }
8033 
8034 NK_API void
8035 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
8036  const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
8037  float thickness, enum nk_anti_aliasing aliasing)
8038 {
8039  nk_size count;
8040  int thick_line;
8041  struct nk_colorf col;
8042  struct nk_colorf col_trans;
8043  NK_ASSERT(list);
8044  if (!list || points_count < 2) return;
8045 
8046  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8047  count = points_count;
8048  if (!closed) count = points_count-1;
8049  thick_line = thickness > 1.0f;
8050 
8051 #ifdef NK_INCLUDE_COMMAND_USERDATA
8052  nk_draw_list_push_userdata(list, list->userdata);
8053 #endif
8054 
8055  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8056  nk_color_fv(&col.r, color);
8057  col_trans = col;
8058  col_trans.a = 0;
8059 
8060  if (aliasing == NK_ANTI_ALIASING_ON) {
8061  /* ANTI-ALIASED STROKE */
8062  const float AA_SIZE = 1.0f;
8063  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
8064  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
8065 
8066  /* allocate vertices and elements */
8067  nk_size i1 = 0;
8068  nk_size vertex_offset;
8069  nk_size index = list->vertex_count;
8070 
8071  const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12);
8072  const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
8073 
8074  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8075  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8076 
8077  nk_size size;
8078  struct nk_vec2 *normals, *temp;
8079  if (!vtx || !ids) return;
8080 
8081  /* temporary allocate normals + points */
8082  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
8083  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
8084  size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
8085  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
8086  NK_ASSERT(normals);
8087  if (!normals) return;
8088  temp = normals + points_count;
8089 
8090  /* make sure vertex pointer is still correct */
8091  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
8092 
8093  /* calculate normals */
8094  for (i1 = 0; i1 < count; ++i1) {
8095  const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
8096  struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
8097  float len;
8098 
8099  /* vec2 inverted length */
8100  len = nk_vec2_len_sqr(diff);
8101  if (len != 0.0f)
8102  len = nk_inv_sqrt(len);
8103  else len = 1.0f;
8104 
8105  diff = nk_vec2_muls(diff, len);
8106  normals[i1].x = diff.y;
8107  normals[i1].y = -diff.x;
8108  }
8109 
8110  if (!closed)
8111  normals[points_count-1] = normals[points_count-2];
8112 
8113  if (!thick_line) {
8114  nk_size idx1, i;
8115  if (!closed) {
8116  struct nk_vec2 d;
8117  temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
8118  temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
8119  d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
8120  temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
8121  temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
8122  }
8123 
8124  /* fill elements */
8125  idx1 = index;
8126  for (i1 = 0; i1 < count; i1++) {
8127  struct nk_vec2 dm;
8128  float dmr2;
8129  nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
8130  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
8131 
8132  /* average normals */
8133  dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
8134  dmr2 = dm.x * dm.x + dm.y* dm.y;
8135  if (dmr2 > 0.000001f) {
8136  float scale = 1.0f/dmr2;
8137  scale = NK_MIN(100.0f, scale);
8138  dm = nk_vec2_muls(dm, scale);
8139  }
8140 
8141  dm = nk_vec2_muls(dm, AA_SIZE);
8142  temp[i2*2+0] = nk_vec2_add(points[i2], dm);
8143  temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
8144 
8145  ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
8146  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
8147  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
8148  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
8149  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
8150  ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
8151  ids += 12;
8152  idx1 = idx2;
8153  }
8154 
8155  /* fill vertices */
8156  for (i = 0; i < points_count; ++i) {
8157  const struct nk_vec2 uv = list->config.null.uv;
8158  vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
8159  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
8160  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
8161  }
8162  } else {
8163  nk_size idx1, i;
8164  const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
8165  if (!closed) {
8166  struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
8167  struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
8168 
8169  temp[0] = nk_vec2_add(points[0], d1);
8170  temp[1] = nk_vec2_add(points[0], d2);
8171  temp[2] = nk_vec2_sub(points[0], d2);
8172  temp[3] = nk_vec2_sub(points[0], d1);
8173 
8174  d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
8175  d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
8176 
8177  temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
8178  temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
8179  temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
8180  temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
8181  }
8182 
8183  /* add all elements */
8184  idx1 = index;
8185  for (i1 = 0; i1 < count; ++i1) {
8186  struct nk_vec2 dm_out, dm_in;
8187  const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
8188  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
8189 
8190  /* average normals */
8191  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
8192  float dmr2 = dm.x * dm.x + dm.y* dm.y;
8193  if (dmr2 > 0.000001f) {
8194  float scale = 1.0f/dmr2;
8195  scale = NK_MIN(100.0f, scale);
8196  dm = nk_vec2_muls(dm, scale);
8197  }
8198 
8199  dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
8200  dm_in = nk_vec2_muls(dm, half_inner_thickness);
8201  temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
8202  temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
8203  temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
8204  temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
8205 
8206  /* add indexes */
8207  ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
8208  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
8209  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
8210  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
8211  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
8212  ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
8213  ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
8214  ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
8215  ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
8216  ids += 18;
8217  idx1 = idx2;
8218  }
8219 
8220  /* add vertices */
8221  for (i = 0; i < points_count; ++i) {
8222  const struct nk_vec2 uv = list->config.null.uv;
8223  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
8224  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
8225  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
8226  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
8227  }
8228  }
8229  /* free temporary normals + points */
8230  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
8231  } else {
8232  /* NON ANTI-ALIASED STROKE */
8233  nk_size i1 = 0;
8234  nk_size idx = list->vertex_count;
8235  const nk_size idx_count = count * 6;
8236  const nk_size vtx_count = count * 4;
8237  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8238  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8239  if (!vtx || !ids) return;
8240 
8241  for (i1 = 0; i1 < count; ++i1) {
8242  float dx, dy;
8243  const struct nk_vec2 uv = list->config.null.uv;
8244  const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
8245  const struct nk_vec2 p1 = points[i1];
8246  const struct nk_vec2 p2 = points[i2];
8247  struct nk_vec2 diff = nk_vec2_sub(p2, p1);
8248  float len;
8249 
8250  /* vec2 inverted length */
8251  len = nk_vec2_len_sqr(diff);
8252  if (len != 0.0f)
8253  len = nk_inv_sqrt(len);
8254  else len = 1.0f;
8255  diff = nk_vec2_muls(diff, len);
8256 
8257  /* add vertices */
8258  dx = diff.x * (thickness * 0.5f);
8259  dy = diff.y * (thickness * 0.5f);
8260 
8261  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
8262  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
8263  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
8264  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
8265 
8266  ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
8267  ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
8268  ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
8269 
8270  ids += 6;
8271  idx += 4;
8272  }
8273  }
8274 }
8275 
8276 NK_API void
8277 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
8278  const struct nk_vec2 *points, const unsigned int points_count,
8279  struct nk_color color, enum nk_anti_aliasing aliasing)
8280 {
8281  struct nk_colorf col;
8282  struct nk_colorf col_trans;
8283 
8284  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
8285  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
8286  NK_ASSERT(list);
8287  if (!list || points_count < 3) return;
8288 
8289 #ifdef NK_INCLUDE_COMMAND_USERDATA
8290  nk_draw_list_push_userdata(list, list->userdata);
8291 #endif
8292 
8293  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8294  nk_color_fv(&col.r, color);
8295  col_trans = col;
8296  col_trans.a = 0;
8297 
8298  if (aliasing == NK_ANTI_ALIASING_ON) {
8299  nk_size i = 0;
8300  nk_size i0 = 0;
8301  nk_size i1 = 0;
8302 
8303  const float AA_SIZE = 1.0f;
8304  nk_size vertex_offset = 0;
8305  nk_size index = list->vertex_count;
8306 
8307  const nk_size idx_count = (points_count-2)*3 + points_count*6;
8308  const nk_size vtx_count = (points_count*2);
8309 
8310  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8311  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8312 
8313  nk_size size = 0;
8314  struct nk_vec2 *normals = 0;
8315  unsigned int vtx_inner_idx = (unsigned int)(index + 0);
8316  unsigned int vtx_outer_idx = (unsigned int)(index + 1);
8317  if (!vtx || !ids) return;
8318 
8319  /* temporary allocate normals */
8320  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
8321  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
8322  size = pnt_size * points_count;
8323  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
8324  NK_ASSERT(normals);
8325  if (!normals) return;
8326  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
8327 
8328  /* add elements */
8329  for (i = 2; i < points_count; i++) {
8330  ids[0] = (nk_draw_index)(vtx_inner_idx);
8331  ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
8332  ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
8333  ids += 3;
8334  }
8335 
8336  /* compute normals */
8337  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
8338  struct nk_vec2 p0 = points[i0];
8339  struct nk_vec2 p1 = points[i1];
8340  struct nk_vec2 diff = nk_vec2_sub(p1, p0);
8341 
8342  /* vec2 inverted length */
8343  float len = nk_vec2_len_sqr(diff);
8344  if (len != 0.0f)
8345  len = nk_inv_sqrt(len);
8346  else len = 1.0f;
8347  diff = nk_vec2_muls(diff, len);
8348 
8349  normals[i0].x = diff.y;
8350  normals[i0].y = -diff.x;
8351  }
8352 
8353  /* add vertices + indexes */
8354  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
8355  const struct nk_vec2 uv = list->config.null.uv;
8356  struct nk_vec2 n0 = normals[i0];
8357  struct nk_vec2 n1 = normals[i1];
8358  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
8359  float dmr2 = dm.x*dm.x + dm.y*dm.y;
8360  if (dmr2 > 0.000001f) {
8361  float scale = 1.0f / dmr2;
8362  scale = NK_MIN(scale, 100.0f);
8363  dm = nk_vec2_muls(dm, scale);
8364  }
8365  dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
8366 
8367  /* add vertices */
8368  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
8369  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
8370 
8371  /* add indexes */
8372  ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
8373  ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
8374  ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
8375  ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
8376  ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
8377  ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
8378  ids += 6;
8379  }
8380  /* free temporary normals + points */
8381  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
8382  } else {
8383  nk_size i = 0;
8384  nk_size index = list->vertex_count;
8385  const nk_size idx_count = (points_count-2)*3;
8386  const nk_size vtx_count = points_count;
8387  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8388  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8389 
8390  if (!vtx || !ids) return;
8391  for (i = 0; i < vtx_count; ++i)
8392  vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
8393  for (i = 2; i < points_count; ++i) {
8394  ids[0] = (nk_draw_index)index;
8395  ids[1] = (nk_draw_index)(index+ i - 1);
8396  ids[2] = (nk_draw_index)(index+i);
8397  ids += 3;
8398  }
8399  }
8400 }
8401 
8402 NK_API void
8403 nk_draw_list_path_clear(struct nk_draw_list *list)
8404 {
8405  NK_ASSERT(list);
8406  if (!list) return;
8407  nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
8408  list->path_count = 0;
8409  list->path_offset = 0;
8410 }
8411 
8412 NK_API void
8413 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
8414 {
8415  struct nk_vec2 *points = 0;
8416  struct nk_draw_command *cmd = 0;
8417  NK_ASSERT(list);
8418  if (!list) return;
8419  if (!list->cmd_count)
8420  nk_draw_list_add_clip(list, nk_null_rect);
8421 
8422  cmd = nk_draw_list_command_last(list);
8423  if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
8424  nk_draw_list_push_image(list, list->config.null.texture);
8425 
8426  points = nk_draw_list_alloc_path(list, 1);
8427  if (!points) return;
8428  points[0] = pos;
8429 }
8430 
8431 NK_API void
8432 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
8433  float radius, int a_min, int a_max)
8434 {
8435  int a = 0;
8436  NK_ASSERT(list);
8437  if (!list) return;
8438  if (a_min <= a_max) {
8439  for (a = a_min; a <= a_max; a++) {
8440  const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
8441  const float x = center.x + c.x * radius;
8442  const float y = center.y + c.y * radius;
8443  nk_draw_list_path_line_to(list, nk_vec2(x, y));
8444  }
8445  }
8446 }
8447 
8448 NK_API void
8449 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
8450  float radius, float a_min, float a_max, unsigned int segments)
8451 {
8452  unsigned int i = 0;
8453  NK_ASSERT(list);
8454  if (!list) return;
8455  if (radius == 0.0f) return;
8456  for (i = 0; i <= segments; ++i) {
8457  const float a = a_min + ((float)i / ((float)segments) * (a_max - a_min));
8458  const float x = center.x + (float)NK_COS(a) * radius;
8459  const float y = center.y + (float)NK_SIN(a) * radius;
8460  nk_draw_list_path_line_to(list, nk_vec2(x, y));
8461  }
8462 }
8463 
8464 NK_API void
8465 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
8466  struct nk_vec2 b, float rounding)
8467 {
8468  float r;
8469  NK_ASSERT(list);
8470  if (!list) return;
8471  r = rounding;
8472  r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
8473  r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
8474 
8475  if (r == 0.0f) {
8476  nk_draw_list_path_line_to(list, a);
8477  nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
8478  nk_draw_list_path_line_to(list, b);
8479  nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
8480  } else {
8481  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
8482  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
8483  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
8484  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
8485  }
8486 }
8487 
8488 NK_API void
8489 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
8490  struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
8491 {
8492  float t_step;
8493  unsigned int i_step;
8494  struct nk_vec2 p1;
8495 
8496  NK_ASSERT(list);
8497  NK_ASSERT(list->path_count);
8498  if (!list || !list->path_count) return;
8499  num_segments = NK_MAX(num_segments, 1);
8500 
8501  p1 = nk_draw_list_path_last(list);
8502  t_step = 1.0f/(float)num_segments;
8503  for (i_step = 1; i_step <= num_segments; ++i_step) {
8504  float t = t_step * (float)i_step;
8505  float u = 1.0f - t;
8506  float w1 = u*u*u;
8507  float w2 = 3*u*u*t;
8508  float w3 = 3*u*t*t;
8509  float w4 = t * t *t;
8510  float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
8511  float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
8512  nk_draw_list_path_line_to(list, nk_vec2(x,y));
8513  }
8514 }
8515 
8516 NK_API void
8517 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
8518 {
8519  struct nk_vec2 *points;
8520  NK_ASSERT(list);
8521  if (!list) return;
8522  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
8523  nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
8524  nk_draw_list_path_clear(list);
8525 }
8526 
8527 NK_API void
8528 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
8529  enum nk_draw_list_stroke closed, float thickness)
8530 {
8531  struct nk_vec2 *points;
8532  NK_ASSERT(list);
8533  if (!list) return;
8534  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
8535  nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
8536  closed, thickness, list->config.line_AA);
8537  nk_draw_list_path_clear(list);
8538 }
8539 
8540 NK_API void
8541 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
8542  struct nk_vec2 b, struct nk_color col, float thickness)
8543 {
8544  NK_ASSERT(list);
8545  if (!list || !col.a) return;
8546  nk_draw_list_path_line_to(list, nk_vec2_add(a, nk_vec2(0.5f, 0.5f)));
8547  nk_draw_list_path_line_to(list, nk_vec2_add(b, nk_vec2(0.5f, 0.5f)));
8548  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
8549 }
8550 
8551 NK_API void
8552 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
8553  struct nk_color col, float rounding)
8554 {
8555  NK_ASSERT(list);
8556  if (!list || !col.a) return;
8557  nk_draw_list_path_rect_to(list, nk_vec2(rect.x + 0.5f, rect.y + 0.5f),
8558  nk_vec2(rect.x + rect.w + 0.5f, rect.y + rect.h + 0.5f), rounding);
8559  nk_draw_list_path_fill(list, col);
8560 }
8561 
8562 NK_API void
8563 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
8564  struct nk_color col, float rounding, float thickness)
8565 {
8566  NK_ASSERT(list);
8567  if (!list || !col.a) return;
8568  nk_draw_list_path_rect_to(list, nk_vec2(rect.x + 0.5f, rect.y + 0.5f),
8569  nk_vec2(rect.x + rect.w + 0.5f, rect.y + rect.h + 0.5f), rounding);
8570  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8571 }
8572 
8573 NK_API void
8574 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
8575  struct nk_color left, struct nk_color top, struct nk_color right,
8576  struct nk_color bottom)
8577 {
8578  void *vtx;
8579  struct nk_colorf col_left, col_top;
8580  struct nk_colorf col_right, col_bottom;
8581  nk_draw_index *idx;
8582  nk_draw_index index;
8583 
8584  nk_color_fv(&col_left.r, left);
8585  nk_color_fv(&col_right.r, right);
8586  nk_color_fv(&col_top.r, top);
8587  nk_color_fv(&col_bottom.r, bottom);
8588 
8589  NK_ASSERT(list);
8590  if (!list) return;
8591 
8592  nk_draw_list_push_image(list, list->config.null.texture);
8593  index = (nk_draw_index)list->vertex_count;
8594  vtx = nk_draw_list_alloc_vertices(list, 4);
8595  idx = nk_draw_list_alloc_elements(list, 6);
8596  if (!vtx || !idx) return;
8597 
8598  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
8599  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
8600  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
8601 
8602  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
8603  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
8604  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
8605  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
8606 }
8607 
8608 NK_API void
8609 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
8610  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
8611 {
8612  NK_ASSERT(list);
8613  if (!list || !col.a) return;
8614  nk_draw_list_path_line_to(list, a);
8615  nk_draw_list_path_line_to(list, b);
8616  nk_draw_list_path_line_to(list, c);
8617  nk_draw_list_path_fill(list, col);
8618 }
8619 
8620 NK_API void
8621 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
8622  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
8623 {
8624  NK_ASSERT(list);
8625  if (!list || !col.a) return;
8626  nk_draw_list_path_line_to(list, a);
8627  nk_draw_list_path_line_to(list, b);
8628  nk_draw_list_path_line_to(list, c);
8629  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8630 }
8631 
8632 NK_API void
8633 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
8634  float radius, struct nk_color col, unsigned int segs)
8635 {
8636  float a_max;
8637  NK_ASSERT(list);
8638  if (!list || !col.a) return;
8639  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
8640  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
8641  nk_draw_list_path_fill(list, col);
8642 }
8643 
8644 NK_API void
8645 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
8646  float radius, struct nk_color col, unsigned int segs, float thickness)
8647 {
8648  float a_max;
8649  NK_ASSERT(list);
8650  if (!list || !col.a) return;
8651  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
8652  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
8653  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8654 }
8655 
8656 NK_API void
8657 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
8658  struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
8659  struct nk_color col, unsigned int segments, float thickness)
8660 {
8661  NK_ASSERT(list);
8662  if (!list || !col.a) return;
8663  nk_draw_list_path_line_to(list, p0);
8664  nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
8665  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
8666 }
8667 
8668 NK_INTERN void
8669 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
8670  struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
8671  struct nk_color color)
8672 {
8673  void *vtx;
8674  struct nk_vec2 uvb;
8675  struct nk_vec2 uvd;
8676  struct nk_vec2 b;
8677  struct nk_vec2 d;
8678 
8679  struct nk_colorf col;
8680  nk_draw_index *idx;
8681  nk_draw_index index;
8682  NK_ASSERT(list);
8683  if (!list) return;
8684 
8685  nk_color_fv(&col.r, color);
8686  uvb = nk_vec2(uvc.x, uva.y);
8687  uvd = nk_vec2(uva.x, uvc.y);
8688  b = nk_vec2(c.x, a.y);
8689  d = nk_vec2(a.x, c.y);
8690 
8691  index = (nk_draw_index)list->vertex_count;
8692  vtx = nk_draw_list_alloc_vertices(list, 4);
8693  idx = nk_draw_list_alloc_elements(list, 6);
8694  if (!vtx || !idx) return;
8695 
8696  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
8697  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
8698  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
8699 
8700  vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
8701  vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
8702  vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
8703  vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
8704 }
8705 
8706 NK_API void
8707 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
8708  struct nk_rect rect, struct nk_color color)
8709 {
8710  NK_ASSERT(list);
8711  if (!list) return;
8712  /* push new command with given texture */
8713  nk_draw_list_push_image(list, texture.handle);
8714  if (nk_image_is_subimage(&texture)) {
8715  /* add region inside of the texture */
8716  struct nk_vec2 uv[2];
8717  uv[0].x = (float)texture.region[0]/(float)texture.w;
8718  uv[0].y = (float)texture.region[1]/(float)texture.h;
8719  uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
8720  uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
8721  nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
8722  nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color);
8723  } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
8724  nk_vec2(rect.x + rect.w, rect.y + rect.h),
8725  nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
8726 }
8727 
8728 NK_API void
8729 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
8730  struct nk_rect rect, const char *text, int len, float font_height,
8731  struct nk_color fg)
8732 {
8733  float x = 0;
8734  int text_len = 0;
8735  nk_rune unicode = 0;
8736  nk_rune next = 0;
8737  int glyph_len = 0;
8738  int next_glyph_len = 0;
8739  struct nk_user_font_glyph g;
8740 
8741  NK_ASSERT(list);
8742  if (!list || !len || !text) return;
8743  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8744  list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
8745 
8746  nk_draw_list_push_image(list, font->texture);
8747  x = rect.x;
8748  glyph_len = nk_utf_decode(text, &unicode, len);
8749  if (!glyph_len) return;
8750 
8751  /* draw every glyph image */
8752  fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
8753  while (text_len < len && glyph_len) {
8754  float gx, gy, gh, gw;
8755  float char_width = 0;
8756  if (unicode == NK_UTF_INVALID) break;
8757 
8758  /* query currently drawn glyph information */
8759  next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
8760  font->query(font->userdata, font_height, &g, unicode,
8761  (next == NK_UTF_INVALID) ? '\0' : next);
8762 
8763  /* calculate and draw glyph drawing rectangle and image */
8764  gx = x + g.offset.x;
8765  gy = rect.y + g.offset.y;
8766  gw = g.width; gh = g.height;
8767  char_width = g.xadvance;
8768  nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
8769  g.uv[0], g.uv[1], fg);
8770 
8771  /* offset next glyph */
8772  text_len += glyph_len;
8773  x += char_width;
8774  glyph_len = next_glyph_len;
8775  unicode = next;
8776  }
8777 }
8778 
8779 NK_API nk_flags
8780 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
8781  struct nk_buffer *vertices, struct nk_buffer *elements,
8782  const struct nk_convert_config *config)
8783 {
8784  nk_flags res = NK_CONVERT_SUCCESS;
8785  const struct nk_command *cmd;
8786  NK_ASSERT(ctx);
8787  NK_ASSERT(cmds);
8788  NK_ASSERT(vertices);
8789  NK_ASSERT(elements);
8790  NK_ASSERT(config);
8791  NK_ASSERT(config->vertex_layout);
8792  NK_ASSERT(config->vertex_size);
8793  if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
8794  return NK_CONVERT_INVALID_PARAM;
8795 
8796  nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements);
8797  nk_foreach(cmd, ctx)
8798  {
8799 #ifdef NK_INCLUDE_COMMAND_USERDATA
8800  ctx->draw_list.userdata = cmd->userdata;
8801 #endif
8802  switch (cmd->type) {
8803  case NK_COMMAND_NOP: break;
8804  case NK_COMMAND_SCISSOR: {
8805  const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
8806  nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
8807  } break;
8808  case NK_COMMAND_LINE: {
8809  const struct nk_command_line *l = (const struct nk_command_line*)cmd;
8810  nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
8811  nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
8812  } break;
8813  case NK_COMMAND_CURVE: {
8814  const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
8815  nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
8816  nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
8817  q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
8818  config->curve_segment_count, q->line_thickness);
8819  } break;
8820  case NK_COMMAND_RECT: {
8821  const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
8822  nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
8823  r->color, (float)r->rounding, r->line_thickness);
8824  } break;
8825  case NK_COMMAND_RECT_FILLED: {
8826  const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
8827  nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
8828  r->color, (float)r->rounding);
8829  } break;
8831  const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
8832  nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
8833  r->left, r->top, r->right, r->bottom);
8834  } break;
8835  case NK_COMMAND_CIRCLE: {
8836  const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
8837  nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
8838  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
8839  config->circle_segment_count, c->line_thickness);
8840  } break;
8841  case NK_COMMAND_CIRCLE_FILLED: {
8842  const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
8843  nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
8844  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
8845  config->circle_segment_count);
8846  } break;
8847  case NK_COMMAND_ARC: {
8848  const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
8849  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
8850  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
8851  c->a[0], c->a[1], config->arc_segment_count);
8852  nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
8853  } break;
8854  case NK_COMMAND_ARC_FILLED: {
8855  const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
8856  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
8857  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
8858  c->a[0], c->a[1], config->arc_segment_count);
8859  nk_draw_list_path_fill(&ctx->draw_list, c->color);
8860  } break;
8861  case NK_COMMAND_TRIANGLE: {
8862  const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
8863  nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
8864  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
8865  t->line_thickness);
8866  } break;
8868  const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
8869  nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
8870  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
8871  } break;
8872  case NK_COMMAND_POLYGON: {
8873  int i;
8874  const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
8875  for (i = 0; i < p->point_count; ++i) {
8876  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
8877  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
8878  }
8879  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
8880  } break;
8882  int i;
8883  const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
8884  for (i = 0; i < p->point_count; ++i) {
8885  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
8886  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
8887  }
8888  nk_draw_list_path_fill(&ctx->draw_list, p->color);
8889  } break;
8890  case NK_COMMAND_POLYLINE: {
8891  int i;
8892  const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
8893  for (i = 0; i < p->point_count; ++i) {
8894  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
8895  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
8896  }
8897  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
8898  } break;
8899  case NK_COMMAND_TEXT: {
8900  const struct nk_command_text *t = (const struct nk_command_text*)cmd;
8901  nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
8902  t->string, t->length, t->height, t->foreground);
8903  } break;
8904  case NK_COMMAND_IMAGE: {
8905  const struct nk_command_image *i = (const struct nk_command_image*)cmd;
8906  nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
8907  } break;
8908  case NK_COMMAND_CUSTOM: {
8909  const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
8910  c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
8911  } break;
8912  default: break;
8913  }
8914  }
8915  res |= (cmds->needed > cmds->allocated) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
8916  res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
8917  res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
8918  return res;
8919 }
8920 NK_API const struct nk_draw_command*
8921 nk__draw_begin(const struct nk_context *ctx,
8922  const struct nk_buffer *buffer)
8923 {return nk__draw_list_begin(&ctx->draw_list, buffer);}
8924 
8925 NK_API const struct nk_draw_command*
8926 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
8927 {return nk__draw_list_end(&ctx->draw_list, buffer);}
8928 
8929 NK_API const struct nk_draw_command*
8930 nk__draw_next(const struct nk_draw_command *cmd,
8931  const struct nk_buffer *buffer, const struct nk_context *ctx)
8932 {return nk__draw_list_next(cmd, buffer, &ctx->draw_list);}
8933 
8934 #endif
8935 
8936 /*
8937  * ==============================================================
8938  *
8939  * FONT HANDLING
8940  *
8941  * ===============================================================
8942  */
8943 #ifdef NK_INCLUDE_FONT_BAKING
8944 /* -------------------------------------------------------------
8945  *
8946  * RECT PACK
8947  *
8948  * --------------------------------------------------------------*/
8949 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */
8950 /* Sean Barrett 2014 */
8951 #define NK_RP__MAXVAL 0xffff
8952 typedef unsigned short nk_rp_coord;
8953 
8954 struct nk_rp_rect {
8955  /* reserved for your use: */
8956  int id;
8957  /* input: */
8958  nk_rp_coord w, h;
8959  /* output: */
8960  nk_rp_coord x, y;
8961  int was_packed;
8962  /* non-zero if valid packing */
8963 }; /* 16 bytes, nominally */
8964 
8965 struct nk_rp_node {
8966  nk_rp_coord x,y;
8967  struct nk_rp_node *next;
8968 };
8969 
8970 struct nk_rp_context {
8971  int width;
8972  int height;
8973  int align;
8974  int init_mode;
8975  int heuristic;
8976  int num_nodes;
8977  struct nk_rp_node *active_head;
8978  struct nk_rp_node *free_head;
8979  struct nk_rp_node extra[2];
8980  /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
8981 };
8982 
8983 struct nk_rp__findresult {
8984  int x,y;
8985  struct nk_rp_node **prev_link;
8986 };
8987 
8988 enum NK_RP_HEURISTIC {
8989  NK_RP_HEURISTIC_Skyline_default=0,
8990  NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default,
8991  NK_RP_HEURISTIC_Skyline_BF_sortHeight
8992 };
8993 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1};
8994 
8995 NK_INTERN void
8996 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem)
8997 {
8998  if (allow_out_of_mem)
8999  /* if it's ok to run out of memory, then don't bother aligning them; */
9000  /* this gives better packing, but may fail due to OOM (even though */
9001  /* the rectangles easily fit). @TODO a smarter approach would be to only */
9002  /* quantize once we've hit OOM, then we could get rid of this parameter. */
9003  context->align = 1;
9004  else {
9005  /* if it's not ok to run out of memory, then quantize the widths */
9006  /* so that num_nodes is always enough nodes. */
9007  /* */
9008  /* I.e. num_nodes * align >= width */
9009  /* align >= width / num_nodes */
9010  /* align = ceil(width/num_nodes) */
9011  context->align = (context->width + context->num_nodes-1) / context->num_nodes;
9012  }
9013 }
9014 
9015 NK_INTERN void
9016 nk_rp_init_target(struct nk_rp_context *context, int width, int height,
9017  struct nk_rp_node *nodes, int num_nodes)
9018 {
9019  int i;
9020 #ifndef STBRP_LARGE_RECTS
9021  NK_ASSERT(width <= 0xffff && height <= 0xffff);
9022 #endif
9023 
9024  for (i=0; i < num_nodes-1; ++i)
9025  nodes[i].next = &nodes[i+1];
9026  nodes[i].next = 0;
9027  context->init_mode = NK_RP__INIT_skyline;
9028  context->heuristic = NK_RP_HEURISTIC_Skyline_default;
9029  context->free_head = &nodes[0];
9030  context->active_head = &context->extra[0];
9031  context->width = width;
9032  context->height = height;
9033  context->num_nodes = num_nodes;
9034  nk_rp_setup_allow_out_of_mem(context, 0);
9035 
9036  /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
9037  context->extra[0].x = 0;
9038  context->extra[0].y = 0;
9039  context->extra[0].next = &context->extra[1];
9040  context->extra[1].x = (nk_rp_coord) width;
9041  context->extra[1].y = 65535;
9042  context->extra[1].next = 0;
9043 }
9044 
9045 /* find minimum y position if it starts at x1 */
9046 NK_INTERN int
9047 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first,
9048  int x0, int width, int *pwaste)
9049 {
9050  struct nk_rp_node *node = first;
9051  int x1 = x0 + width;
9052  int min_y, visited_width, waste_area;
9053  NK_ASSERT(first->x <= x0);
9054  NK_UNUSED(c);
9055 
9056  NK_ASSERT(node->next->x > x0);
9057  /* we ended up handling this in the caller for efficiency */
9058  NK_ASSERT(node->x <= x0);
9059 
9060  min_y = 0;
9061  waste_area = 0;
9062  visited_width = 0;
9063  while (node->x < x1)
9064  {
9065  if (node->y > min_y) {
9066  /* raise min_y higher. */
9067  /* we've accounted for all waste up to min_y, */
9068  /* but we'll now add more waste for everything we've visited */
9069  waste_area += visited_width * (node->y - min_y);
9070  min_y = node->y;
9071  /* the first time through, visited_width might be reduced */
9072  if (node->x < x0)
9073  visited_width += node->next->x - x0;
9074  else
9075  visited_width += node->next->x - node->x;
9076  } else {
9077  /* add waste area */
9078  int under_width = node->next->x - node->x;
9079  if (under_width + visited_width > width)
9080  under_width = width - visited_width;
9081  waste_area += under_width * (min_y - node->y);
9082  visited_width += under_width;
9083  }
9084  node = node->next;
9085  }
9086  *pwaste = waste_area;
9087  return min_y;
9088 }
9089 
9090 NK_INTERN struct nk_rp__findresult
9091 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height)
9092 {
9093  int best_waste = (1<<30), best_x, best_y = (1 << 30);
9094  struct nk_rp__findresult fr;
9095  struct nk_rp_node **prev, *node, *tail, **best = 0;
9096 
9097  /* align to multiple of c->align */
9098  width = (width + c->align - 1);
9099  width -= width % c->align;
9100  NK_ASSERT(width % c->align == 0);
9101 
9102  node = c->active_head;
9103  prev = &c->active_head;
9104  while (node->x + width <= c->width) {
9105  int y,waste;
9106  y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste);
9107  /* actually just want to test BL */
9108  if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) {
9109  /* bottom left */
9110  if (y < best_y) {
9111  best_y = y;
9112  best = prev;
9113  }
9114  } else {
9115  /* best-fit */
9116  if (y + height <= c->height) {
9117  /* can only use it if it first vertically */
9118  if (y < best_y || (y == best_y && waste < best_waste)) {
9119  best_y = y;
9120  best_waste = waste;
9121  best = prev;
9122  }
9123  }
9124  }
9125  prev = &node->next;
9126  node = node->next;
9127  }
9128  best_x = (best == 0) ? 0 : (*best)->x;
9129 
9130  /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
9131  /* */
9132  /* e.g, if fitting */
9133  /* */
9134  /* ____________________ */
9135  /* |____________________| */
9136  /* */
9137  /* into */
9138  /* */
9139  /* | | */
9140  /* | ____________| */
9141  /* |____________| */
9142  /* */
9143  /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
9144  /* */
9145  /* This makes BF take about 2x the time */
9146  if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight)
9147  {
9148  tail = c->active_head;
9149  node = c->active_head;
9150  prev = &c->active_head;
9151  /* find first node that's admissible */
9152  while (tail->x < width)
9153  tail = tail->next;
9154  while (tail)
9155  {
9156  int xpos = tail->x - width;
9157  int y,waste;
9158  NK_ASSERT(xpos >= 0);
9159  /* find the left position that matches this */
9160  while (node->next->x <= xpos) {
9161  prev = &node->next;
9162  node = node->next;
9163  }
9164  NK_ASSERT(node->next->x > xpos && node->x <= xpos);
9165  y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste);
9166  if (y + height < c->height) {
9167  if (y <= best_y) {
9168  if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
9169  best_x = xpos;
9170  NK_ASSERT(y <= best_y);
9171  best_y = y;
9172  best_waste = waste;
9173  best = prev;
9174  }
9175  }
9176  }
9177  tail = tail->next;
9178  }
9179  }
9180  fr.prev_link = best;
9181  fr.x = best_x;
9182  fr.y = best_y;
9183  return fr;
9184 }
9185 
9186 NK_INTERN struct nk_rp__findresult
9187 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height)
9188 {
9189  /* find best position according to heuristic */
9190  struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height);
9191  struct nk_rp_node *node, *cur;
9192 
9193  /* bail if: */
9194  /* 1. it failed */
9195  /* 2. the best node doesn't fit (we don't always check this) */
9196  /* 3. we're out of memory */
9197  if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) {
9198  res.prev_link = 0;
9199  return res;
9200  }
9201 
9202  /* on success, create new node */
9203  node = context->free_head;
9204  node->x = (nk_rp_coord) res.x;
9205  node->y = (nk_rp_coord) (res.y + height);
9206 
9207  context->free_head = node->next;
9208 
9209  /* insert the new node into the right starting point, and */
9210  /* let 'cur' point to the remaining nodes needing to be */
9211  /* stitched back in */
9212  cur = *res.prev_link;
9213  if (cur->x < res.x) {
9214  /* preserve the existing one, so start testing with the next one */
9215  struct nk_rp_node *next = cur->next;
9216  cur->next = node;
9217  cur = next;
9218  } else {
9219  *res.prev_link = node;
9220  }
9221 
9222  /* from here, traverse cur and free the nodes, until we get to one */
9223  /* that shouldn't be freed */
9224  while (cur->next && cur->next->x <= res.x + width) {
9225  struct nk_rp_node *next = cur->next;
9226  /* move the current node to the free list */
9227  cur->next = context->free_head;
9228  context->free_head = cur;
9229  cur = next;
9230  }
9231  /* stitch the list back in */
9232  node->next = cur;
9233 
9234  if (cur->x < res.x + width)
9235  cur->x = (nk_rp_coord) (res.x + width);
9236  return res;
9237 }
9238 
9239 NK_INTERN int
9240 nk_rect_height_compare(const void *a, const void *b)
9241 {
9242  const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
9243  const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
9244  if (p->h > q->h)
9245  return -1;
9246  if (p->h < q->h)
9247  return 1;
9248  return (p->w > q->w) ? -1 : (p->w < q->w);
9249 }
9250 
9251 NK_INTERN int
9252 nk_rect_original_order(const void *a, const void *b)
9253 {
9254  const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
9255  const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
9256  return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
9257 }
9258 
9259 NK_INTERN void
9260 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*))
9261 {
9262  /* iterative quick sort */
9263  #define NK_MAX_SORT_STACK 64
9264  unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0;
9265  unsigned seed = len/2 * 69069+1;
9266  for (;;) {
9267  for (; left+1 < len; len++) {
9268  struct nk_rp_rect pivot, tmp;
9269  if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0];
9270  pivot = array[left+seed%(len-left)];
9271  seed = seed * 69069 + 1;
9272  stack[pos++] = len;
9273  for (right = left-1;;) {
9274  while (cmp(&array[++right], &pivot) < 0);
9275  while (cmp(&pivot, &array[--len]) < 0);
9276  if (right >= len) break;
9277  tmp = array[right];
9278  array[right] = array[len];
9279  array[len] = tmp;
9280  }
9281  }
9282  if (pos == 0) break;
9283  left = len;
9284  len = stack[--pos];
9285  }
9286  #undef NK_MAX_SORT_STACK
9287 }
9288 
9289 NK_INTERN void
9290 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects)
9291 {
9292  int i;
9293  /* we use the 'was_packed' field internally to allow sorting/unsorting */
9294  for (i=0; i < num_rects; ++i) {
9295  rects[i].was_packed = i;
9296  }
9297 
9298  /* sort according to heuristic */
9299  nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare);
9300 
9301  for (i=0; i < num_rects; ++i) {
9302  struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
9303  if (fr.prev_link) {
9304  rects[i].x = (nk_rp_coord) fr.x;
9305  rects[i].y = (nk_rp_coord) fr.y;
9306  } else {
9307  rects[i].x = rects[i].y = NK_RP__MAXVAL;
9308  }
9309  }
9310 
9311  /* unsort */
9312  nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order);
9313 
9314  /* set was_packed flags */
9315  for (i=0; i < num_rects; ++i)
9316  rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL);
9317 }
9318 
9319 /*
9320  * ==============================================================
9321  *
9322  * TRUETYPE
9323  *
9324  * ===============================================================
9325  */
9326 /* stb_truetype.h - v1.07 - public domain */
9327 #define NK_TT_MAX_OVERSAMPLE 8
9328 #define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1)
9329 
9330 struct nk_tt_bakedchar {
9331  unsigned short x0,y0,x1,y1;
9332  /* coordinates of bbox in bitmap */
9333  float xoff,yoff,xadvance;
9334 };
9335 
9336 struct nk_tt_aligned_quad{
9337  float x0,y0,s0,t0; /* top-left */
9338  float x1,y1,s1,t1; /* bottom-right */
9339 };
9340 
9341 struct nk_tt_packedchar {
9342  unsigned short x0,y0,x1,y1;
9343  /* coordinates of bbox in bitmap */
9344  float xoff,yoff,xadvance;
9345  float xoff2,yoff2;
9346 };
9347 
9348 struct nk_tt_pack_range {
9349  float font_size;
9350  int first_unicode_codepoint_in_range;
9351  /* if non-zero, then the chars are continuous, and this is the first codepoint */
9352  int *array_of_unicode_codepoints;
9353  /* if non-zero, then this is an array of unicode codepoints */
9354  int num_chars;
9355  struct nk_tt_packedchar *chardata_for_range; /* output */
9356  unsigned char h_oversample, v_oversample;
9357  /* don't set these, they're used internally */
9358 };
9359 
9360 struct nk_tt_pack_context {
9361  void *pack_info;
9362  int width;
9363  int height;
9364  int stride_in_bytes;
9365  int padding;
9366  unsigned int h_oversample, v_oversample;
9367  unsigned char *pixels;
9368  void *nodes;
9369 };
9370 
9371 struct nk_tt_fontinfo {
9372  const unsigned char* data; /* pointer to .ttf file */
9373  int fontstart;/* offset of start of font */
9374  int numGlyphs;/* number of glyphs, needed for range checking */
9375  int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */
9376  int index_map; /* a cmap mapping for our chosen character encoding */
9377  int indexToLocFormat; /* format needed to map from glyph index to glyph */
9378 };
9379 
9380 enum {
9381  NK_TT_vmove=1,
9382  NK_TT_vline,
9383  NK_TT_vcurve
9384 };
9385 
9386 struct nk_tt_vertex {
9387  short x,y,cx,cy;
9388  unsigned char type,padding;
9389 };
9390 
9391 struct nk_tt__bitmap{
9392  int w,h,stride;
9393  unsigned char *pixels;
9394 };
9395 
9396 struct nk_tt__hheap_chunk {
9397  struct nk_tt__hheap_chunk *next;
9398 };
9399 struct nk_tt__hheap {
9400  struct nk_allocator alloc;
9401  struct nk_tt__hheap_chunk *head;
9402  void *first_free;
9403  int num_remaining_in_head_chunk;
9404 };
9405 
9406 struct nk_tt__edge {
9407  float x0,y0, x1,y1;
9408  int invert;
9409 };
9410 
9411 struct nk_tt__active_edge {
9412  struct nk_tt__active_edge *next;
9413  float fx,fdx,fdy;
9414  float direction;
9415  float sy;
9416  float ey;
9417 };
9418 struct nk_tt__point {float x,y;};
9419 
9420 #define NK_TT_MACSTYLE_DONTCARE 0
9421 #define NK_TT_MACSTYLE_BOLD 1
9422 #define NK_TT_MACSTYLE_ITALIC 2
9423 #define NK_TT_MACSTYLE_UNDERSCORE 4
9424 #define NK_TT_MACSTYLE_NONE 8
9425 /* <= not same as 0, this makes us check the bitfield is 0 */
9426 
9427 enum { /* platformID */
9428  NK_TT_PLATFORM_ID_UNICODE =0,
9429  NK_TT_PLATFORM_ID_MAC =1,
9430  NK_TT_PLATFORM_ID_ISO =2,
9431  NK_TT_PLATFORM_ID_MICROSOFT =3
9432 };
9433 
9434 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */
9435  NK_TT_UNICODE_EID_UNICODE_1_0 =0,
9436  NK_TT_UNICODE_EID_UNICODE_1_1 =1,
9437  NK_TT_UNICODE_EID_ISO_10646 =2,
9438  NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3,
9439  NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4
9440 };
9441 
9442 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */
9443  NK_TT_MS_EID_SYMBOL =0,
9444  NK_TT_MS_EID_UNICODE_BMP =1,
9445  NK_TT_MS_EID_SHIFTJIS =2,
9446  NK_TT_MS_EID_UNICODE_FULL =10
9447 };
9448 
9449 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */
9450  NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4,
9451  NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5,
9452  NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6,
9453  NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7
9454 };
9455 
9456 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */
9457  /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
9458  NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410,
9459  NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411,
9460  NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412,
9461  NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419,
9462  NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409,
9463  NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D
9464 };
9465 
9466 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */
9467  NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11,
9468  NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23,
9469  NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32,
9470  NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 ,
9471  NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 ,
9472  NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33,
9473  NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19
9474 };
9475 
9476 #define nk_ttBYTE(p) (* (const nk_byte *) (p))
9477 #define nk_ttCHAR(p) (* (const char *) (p))
9478 
9479 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE)
9480  #define nk_ttUSHORT(p) (* (nk_ushort *) (p))
9481  #define nk_ttSHORT(p) (* (nk_short *) (p))
9482  #define nk_ttULONG(p) (* (nk_uint *) (p))
9483  #define nk_ttLONG(p) (* (nk_int *) (p))
9484 #else
9485  static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); }
9486  static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); }
9487  static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); }
9488 #endif
9489 
9490 #define nk_tt_tag4(p,c0,c1,c2,c3)\
9491  ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
9492 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3])
9493 
9494 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
9495  int glyph_index, struct nk_tt_vertex **pvertices);
9496 
9497 NK_INTERN nk_uint
9498 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag)
9499 {
9500  /* @OPTIMIZE: binary search */
9501  nk_int num_tables = nk_ttUSHORT(data+fontstart+4);
9502  nk_uint tabledir = fontstart + 12;
9503  nk_int i;
9504  for (i = 0; i < num_tables; ++i) {
9505  nk_uint loc = tabledir + (nk_uint)(16*i);
9506  if (nk_tt_tag(data+loc+0, tag))
9507  return nk_ttULONG(data+loc+8);
9508  }
9509  return 0;
9510 }
9511 
9512 NK_INTERN int
9513 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart)
9514 {
9515  nk_uint cmap, t;
9516  nk_int i,numTables;
9517  const nk_byte *data = (const nk_byte *) data2;
9518 
9519  info->data = data;
9520  info->fontstart = fontstart;
9521 
9522  cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */
9523  info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */
9524  info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */
9525  info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */
9526  info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */
9527  info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */
9528  info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */
9529  if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
9530  return 0;
9531 
9532  t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp");
9533  if (t) info->numGlyphs = nk_ttUSHORT(data+t+4);
9534  else info->numGlyphs = 0xffff;
9535 
9536  /* find a cmap encoding table we understand *now* to avoid searching */
9537  /* later. (todo: could make this installable) */
9538  /* the same regardless of glyph. */
9539  numTables = nk_ttUSHORT(data + cmap + 2);
9540  info->index_map = 0;
9541  for (i=0; i < numTables; ++i)
9542  {
9543  nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i;
9544  /* find an encoding we understand: */
9545  switch(nk_ttUSHORT(data+encoding_record)) {
9546  case NK_TT_PLATFORM_ID_MICROSOFT:
9547  switch (nk_ttUSHORT(data+encoding_record+2)) {
9548  case NK_TT_MS_EID_UNICODE_BMP:
9549  case NK_TT_MS_EID_UNICODE_FULL:
9550  /* MS/Unicode */
9551  info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
9552  break;
9553  default: break;
9554  } break;
9555  case NK_TT_PLATFORM_ID_UNICODE:
9556  /* Mac/iOS has these */
9557  /* all the encodingIDs are unicode, so we don't bother to check it */
9558  info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
9559  break;
9560  default: break;
9561  }
9562  }
9563  if (info->index_map == 0)
9564  return 0;
9565  info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50);
9566  return 1;
9567 }
9568 
9569 NK_INTERN int
9570 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint)
9571 {
9572  const nk_byte *data = info->data;
9573  nk_uint index_map = (nk_uint)info->index_map;
9574 
9575  nk_ushort format = nk_ttUSHORT(data + index_map + 0);
9576  if (format == 0) { /* apple byte encoding */
9577  nk_int bytes = nk_ttUSHORT(data + index_map + 2);
9578  if (unicode_codepoint < bytes-6)
9579  return nk_ttBYTE(data + index_map + 6 + unicode_codepoint);
9580  return 0;
9581  } else if (format == 6) {
9582  nk_uint first = nk_ttUSHORT(data + index_map + 6);
9583  nk_uint count = nk_ttUSHORT(data + index_map + 8);
9584  if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count)
9585  return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2);
9586  return 0;
9587  } else if (format == 2) {
9588  NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
9589  return 0;
9590  } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
9591  nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1;
9592  nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1;
9593  nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10);
9594  nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1;
9595 
9596  /* do a binary search of the segments */
9597  nk_uint endCount = index_map + 14;
9598  nk_uint search = endCount;
9599 
9600  if (unicode_codepoint > 0xffff)
9601  return 0;
9602 
9603  /* they lie from endCount .. endCount + segCount */
9604  /* but searchRange is the nearest power of two, so... */
9605  if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2))
9606  search += (nk_uint)(rangeShift*2);
9607 
9608  /* now decrement to bias correctly to find smallest */
9609  search -= 2;
9610  while (entrySelector) {
9611  nk_ushort end;
9612  searchRange >>= 1;
9613  end = nk_ttUSHORT(data + search + searchRange*2);
9614  if (unicode_codepoint > end)
9615  search += (nk_uint)(searchRange*2);
9616  --entrySelector;
9617  }
9618  search += 2;
9619 
9620  {
9621  nk_ushort offset, start;
9622  nk_ushort item = (nk_ushort) ((search - endCount) >> 1);
9623 
9624  NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item));
9625  start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
9626  if (unicode_codepoint < start)
9627  return 0;
9628 
9629  offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
9630  if (offset == 0)
9631  return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
9632 
9633  return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
9634  }
9635  } else if (format == 12 || format == 13) {
9636  nk_uint ngroups = nk_ttULONG(data+index_map+12);
9637  nk_int low,high;
9638  low = 0; high = (nk_int)ngroups;
9639  /* Binary search the right group. */
9640  while (low < high) {
9641  nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
9642  nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12);
9643  nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4);
9644  if ((nk_uint) unicode_codepoint < start_char)
9645  high = mid;
9646  else if ((nk_uint) unicode_codepoint > end_char)
9647  low = mid+1;
9648  else {
9649  nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8);
9650  if (format == 12)
9651  return (int)start_glyph + (int)unicode_codepoint - (int)start_char;
9652  else /* format == 13 */
9653  return (int)start_glyph;
9654  }
9655  }
9656  return 0; /* not found */
9657  }
9658  /* @TODO */
9659  NK_ASSERT(0);
9660  return 0;
9661 }
9662 
9663 NK_INTERN void
9664 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy)
9665 {
9666  v->type = type;
9667  v->x = (nk_short) x;
9668  v->y = (nk_short) y;
9669  v->cx = (nk_short) cx;
9670  v->cy = (nk_short) cy;
9671 }
9672 
9673 NK_INTERN int
9674 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index)
9675 {
9676  int g1,g2;
9677  if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
9678  if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */
9679 
9680  if (info->indexToLocFormat == 0) {
9681  g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
9682  g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
9683  } else {
9684  g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4);
9685  g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4);
9686  }
9687  return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
9688 }
9689 
9690 NK_INTERN int
9691 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index,
9692  int *x0, int *y0, int *x1, int *y1)
9693 {
9694  int g = nk_tt__GetGlyfOffset(info, glyph_index);
9695  if (g < 0) return 0;
9696 
9697  if (x0) *x0 = nk_ttSHORT(info->data + g + 2);
9698  if (y0) *y0 = nk_ttSHORT(info->data + g + 4);
9699  if (x1) *x1 = nk_ttSHORT(info->data + g + 6);
9700  if (y1) *y1 = nk_ttSHORT(info->data + g + 8);
9701  return 1;
9702 }
9703 
9704 NK_INTERN int
9705 stbtt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off,
9706  int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy)
9707 {
9708  if (start_off) {
9709  if (was_off)
9710  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
9711  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy);
9712  } else {
9713  if (was_off)
9714  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy);
9715  else
9716  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0);
9717  }
9718  return num_vertices;
9719 }
9720 
9721 NK_INTERN int
9722 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
9723  int glyph_index, struct nk_tt_vertex **pvertices)
9724 {
9725  nk_short numberOfContours;
9726  const nk_byte *endPtsOfContours;
9727  const nk_byte *data = info->data;
9728  struct nk_tt_vertex *vertices=0;
9729  int num_vertices=0;
9730  int g = nk_tt__GetGlyfOffset(info, glyph_index);
9731  *pvertices = 0;
9732 
9733  if (g < 0) return 0;
9734  numberOfContours = nk_ttSHORT(data + g);
9735  if (numberOfContours > 0) {
9736  nk_byte flags=0,flagcount;
9737  nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
9738  nk_int x,y,cx,cy,sx,sy, scx,scy;
9739  const nk_byte *points;
9740  endPtsOfContours = (data + g + 10);
9741  ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2);
9742  points = data + g + 10 + numberOfContours * 2 + 2 + ins;
9743 
9744  n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2);
9745  m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */
9746  vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0]));
9747  if (vertices == 0)
9748  return 0;
9749 
9750  next_move = 0;
9751  flagcount=0;
9752 
9753  /* in first pass, we load uninterpreted data into the allocated array */
9754  /* above, shifted to the end of the array so we won't overwrite it when */
9755  /* we create our final data starting from the front */
9756  off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
9757 
9758  /* first load flags */
9759  for (i=0; i < n; ++i) {
9760  if (flagcount == 0) {
9761  flags = *points++;
9762  if (flags & 8)
9763  flagcount = *points++;
9764  } else --flagcount;
9765  vertices[off+i].type = flags;
9766  }
9767 
9768  /* now load x coordinates */
9769  x=0;
9770  for (i=0; i < n; ++i) {
9771  flags = vertices[off+i].type;
9772  if (flags & 2) {
9773  nk_short dx = *points++;
9774  x += (flags & 16) ? dx : -dx; /* ??? */
9775  } else {
9776  if (!(flags & 16)) {
9777  x = x + (nk_short) (points[0]*256 + points[1]);
9778  points += 2;
9779  }
9780  }
9781  vertices[off+i].x = (nk_short) x;
9782  }
9783 
9784  /* now load y coordinates */
9785  y=0;
9786  for (i=0; i < n; ++i) {
9787  flags = vertices[off+i].type;
9788  if (flags & 4) {
9789  nk_short dy = *points++;
9790  y += (flags & 32) ? dy : -dy; /* ??? */
9791  } else {
9792  if (!(flags & 32)) {
9793  y = y + (nk_short) (points[0]*256 + points[1]);
9794  points += 2;
9795  }
9796  }
9797  vertices[off+i].y = (nk_short) y;
9798  }
9799 
9800  /* now convert them to our format */
9801  num_vertices=0;
9802  sx = sy = cx = cy = scx = scy = 0;
9803  for (i=0; i < n; ++i)
9804  {
9805  flags = vertices[off+i].type;
9806  x = (nk_short) vertices[off+i].x;
9807  y = (nk_short) vertices[off+i].y;
9808 
9809  if (next_move == i) {
9810  if (i != 0)
9811  num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
9812 
9813  /* now start the new one */
9814  start_off = !(flags & 1);
9815  if (start_off) {
9816  /* if we start off with an off-curve point, then when we need to find a point on the curve */
9817  /* where we can start, and we need to save some state for when we wraparound. */
9818  scx = x;
9819  scy = y;
9820  if (!(vertices[off+i+1].type & 1)) {
9821  /* next point is also a curve point, so interpolate an on-point curve */
9822  sx = (x + (nk_int) vertices[off+i+1].x) >> 1;
9823  sy = (y + (nk_int) vertices[off+i+1].y) >> 1;
9824  } else {
9825  /* otherwise just use the next point as our start point */
9826  sx = (nk_int) vertices[off+i+1].x;
9827  sy = (nk_int) vertices[off+i+1].y;
9828  ++i; /* we're using point i+1 as the starting point, so skip it */
9829  }
9830  } else {
9831  sx = x;
9832  sy = y;
9833  }
9834  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0);
9835  was_off = 0;
9836  next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2);
9837  ++j;
9838  } else {
9839  if (!(flags & 1))
9840  { /* if it's a curve */
9841  if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
9842  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
9843  cx = x;
9844  cy = y;
9845  was_off = 1;
9846  } else {
9847  if (was_off)
9848  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy);
9849  else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0);
9850  was_off = 0;
9851  }
9852  }
9853  }
9854  num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
9855  } else if (numberOfContours == -1) {
9856  /* Compound shapes. */
9857  int more = 1;
9858  const nk_byte *comp = data + g + 10;
9859  num_vertices = 0;
9860  vertices = 0;
9861 
9862  while (more)
9863  {
9864  nk_ushort flags, gidx;
9865  int comp_num_verts = 0, i;
9866  struct nk_tt_vertex *comp_verts = 0, *tmp = 0;
9867  float mtx[6] = {1,0,0,1,0,0}, m, n;
9868 
9869  flags = (nk_ushort)nk_ttSHORT(comp); comp+=2;
9870  gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2;
9871 
9872  if (flags & 2) { /* XY values */
9873  if (flags & 1) { /* shorts */
9874  mtx[4] = nk_ttSHORT(comp); comp+=2;
9875  mtx[5] = nk_ttSHORT(comp); comp+=2;
9876  } else {
9877  mtx[4] = nk_ttCHAR(comp); comp+=1;
9878  mtx[5] = nk_ttCHAR(comp); comp+=1;
9879  }
9880  } else {
9881  /* @TODO handle matching point */
9882  NK_ASSERT(0);
9883  }
9884  if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
9885  mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9886  mtx[1] = mtx[2] = 0;
9887  } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
9888  mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9889  mtx[1] = mtx[2] = 0;
9890  mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9891  } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
9892  mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9893  mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9894  mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9895  mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9896  }
9897 
9898  /* Find transformation scales. */
9899  m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
9900  n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
9901 
9902  /* Get indexed glyph. */
9903  comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts);
9904  if (comp_num_verts > 0)
9905  {
9906  /* Transform vertices. */
9907  for (i = 0; i < comp_num_verts; ++i) {
9908  struct nk_tt_vertex* v = &comp_verts[i];
9909  short x,y;
9910  x=v->x; y=v->y;
9911  v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
9912  v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
9913  x=v->cx; y=v->cy;
9914  v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
9915  v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
9916  }
9917  /* Append vertices. */
9918  tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0,
9919  (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex));
9920  if (!tmp) {
9921  if (vertices) alloc->free(alloc->userdata, vertices);
9922  if (comp_verts) alloc->free(alloc->userdata, comp_verts);
9923  return 0;
9924  }
9925  if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex));
9926  NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex));
9927  if (vertices) alloc->free(alloc->userdata,vertices);
9928  vertices = tmp;
9929  alloc->free(alloc->userdata,comp_verts);
9930  num_vertices += comp_num_verts;
9931  }
9932  /* More components ? */
9933  more = flags & (1<<5);
9934  }
9935  } else if (numberOfContours < 0) {
9936  /* @TODO other compound variations? */
9937  NK_ASSERT(0);
9938  } else {
9939  /* numberOfCounters == 0, do nothing */
9940  }
9941  *pvertices = vertices;
9942  return num_vertices;
9943 }
9944 
9945 NK_INTERN void
9946 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index,
9947  int *advanceWidth, int *leftSideBearing)
9948 {
9949  nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34);
9950  if (glyph_index < numOfLongHorMetrics) {
9951  if (advanceWidth)
9952  *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index);
9953  if (leftSideBearing)
9954  *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
9955  } else {
9956  if (advanceWidth)
9957  *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
9958  if (leftSideBearing)
9959  *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
9960  }
9961 }
9962 
9963 NK_INTERN void
9964 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info,
9965  int *ascent, int *descent, int *lineGap)
9966 {
9967  if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4);
9968  if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6);
9969  if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8);
9970 }
9971 
9972 NK_INTERN float
9973 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height)
9974 {
9975  int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6);
9976  return (float) height / (float)fheight;
9977 }
9978 
9979 NK_INTERN float
9980 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels)
9981 {
9982  int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18);
9983  return pixels / (float)unitsPerEm;
9984 }
9985 
9986 /*-------------------------------------------------------------
9987  * antialiasing software rasterizer
9988  * --------------------------------------------------------------*/
9989 NK_INTERN void
9990 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font,
9991  int glyph, float scale_x, float scale_y,float shift_x, float shift_y,
9992  int *ix0, int *iy0, int *ix1, int *iy1)
9993 {
9994  int x0,y0,x1,y1;
9995  if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
9996  /* e.g. space character */
9997  if (ix0) *ix0 = 0;
9998  if (iy0) *iy0 = 0;
9999  if (ix1) *ix1 = 0;
10000  if (iy1) *iy1 = 0;
10001  } else {
10002  /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
10003  if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x);
10004  if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y);
10005  if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x);
10006  if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y);
10007  }
10008 }
10009 
10010 NK_INTERN void
10011 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph,
10012  float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
10013 {
10014  nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
10015 }
10016 
10017 /*-------------------------------------------------------------
10018  * Rasterizer
10019  * --------------------------------------------------------------*/
10020 NK_INTERN void*
10021 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size)
10022 {
10023  if (hh->first_free) {
10024  void *p = hh->first_free;
10025  hh->first_free = * (void **) p;
10026  return p;
10027  } else {
10028  if (hh->num_remaining_in_head_chunk == 0) {
10029  int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
10030  struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *)
10031  hh->alloc.alloc(hh->alloc.userdata, 0,
10032  sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count);
10033  if (c == 0) return 0;
10034  c->next = hh->head;
10035  hh->head = c;
10036  hh->num_remaining_in_head_chunk = count;
10037  }
10038  --hh->num_remaining_in_head_chunk;
10039  return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk;
10040  }
10041 }
10042 
10043 NK_INTERN void
10044 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p)
10045 {
10046  *(void **) p = hh->first_free;
10047  hh->first_free = p;
10048 }
10049 
10050 NK_INTERN void
10051 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh)
10052 {
10053  struct nk_tt__hheap_chunk *c = hh->head;
10054  while (c) {
10055  struct nk_tt__hheap_chunk *n = c->next;
10056  hh->alloc.free(hh->alloc.userdata, c);
10057  c = n;
10058  }
10059 }
10060 
10061 NK_INTERN struct nk_tt__active_edge*
10062 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e,
10063  int off_x, float start_point)
10064 {
10065  struct nk_tt__active_edge *z = (struct nk_tt__active_edge *)
10066  nk_tt__hheap_alloc(hh, sizeof(*z));
10067  float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
10068  /*STBTT_assert(e->y0 <= start_point); */
10069  if (!z) return z;
10070  z->fdx = dxdy;
10071  z->fdy = (dxdy != 0) ? (1/dxdy): 0;
10072  z->fx = e->x0 + dxdy * (start_point - e->y0);
10073  z->fx -= (float)off_x;
10074  z->direction = e->invert ? 1.0f : -1.0f;
10075  z->sy = e->y0;
10076  z->ey = e->y1;
10077  z->next = 0;
10078  return z;
10079 }
10080 
10081 NK_INTERN void
10082 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e,
10083  float x0, float y0, float x1, float y1)
10084 {
10085  if (y0 == y1) return;
10086  NK_ASSERT(y0 < y1);
10087  NK_ASSERT(e->sy <= e->ey);
10088  if (y0 > e->ey) return;
10089  if (y1 < e->sy) return;
10090  if (y0 < e->sy) {
10091  x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
10092  y0 = e->sy;
10093  }
10094  if (y1 > e->ey) {
10095  x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
10096  y1 = e->ey;
10097  }
10098 
10099  if (x0 == x) NK_ASSERT(x1 <= x+1);
10100  else if (x0 == x+1) NK_ASSERT(x1 >= x);
10101  else if (x0 <= x) NK_ASSERT(x1 <= x);
10102  else if (x0 >= x+1) NK_ASSERT(x1 >= x+1);
10103  else NK_ASSERT(x1 >= x && x1 <= x+1);
10104 
10105  if (x0 <= x && x1 <= x)
10106  scanline[x] += e->direction * (y1-y0);
10107  else if (x0 >= x+1 && x1 >= x+1);
10108  else {
10109  NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
10110  /* coverage = 1 - average x position */
10111  scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f);
10112  }
10113 }
10114 
10115 NK_INTERN void
10116 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
10117  struct nk_tt__active_edge *e, float y_top)
10118 {
10119  float y_bottom = y_top+1;
10120  while (e)
10121  {
10122  /* brute force every pixel */
10123  /* compute intersection points with top & bottom */
10124  NK_ASSERT(e->ey >= y_top);
10125  if (e->fdx == 0) {
10126  float x0 = e->fx;
10127  if (x0 < len) {
10128  if (x0 >= 0) {
10129  nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
10130  nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
10131  } else {
10132  nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
10133  }
10134  }
10135  } else {
10136  float x0 = e->fx;
10137  float dx = e->fdx;
10138  float xb = x0 + dx;
10139  float x_top, x_bottom;
10140  float y0,y1;
10141  float dy = e->fdy;
10142  NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top);
10143 
10144  /* compute endpoints of line segment clipped to this scanline (if the */
10145  /* line segment starts on this scanline. x0 is the intersection of the */
10146  /* line with y_top, but that may be off the line segment. */
10147  if (e->sy > y_top) {
10148  x_top = x0 + dx * (e->sy - y_top);
10149  y0 = e->sy;
10150  } else {
10151  x_top = x0;
10152  y0 = y_top;
10153  }
10154 
10155  if (e->ey < y_bottom) {
10156  x_bottom = x0 + dx * (e->ey - y_top);
10157  y1 = e->ey;
10158  } else {
10159  x_bottom = xb;
10160  y1 = y_bottom;
10161  }
10162 
10163  if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len)
10164  {
10165  /* from here on, we don't have to range check x values */
10166  if ((int) x_top == (int) x_bottom) {
10167  float height;
10168  /* simple case, only spans one pixel */
10169  int x = (int) x_top;
10170  height = y1 - y0;
10171  NK_ASSERT(x >= 0 && x < len);
10172  scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height;
10173  scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */
10174  } else {
10175  int x,x1,x2;
10176  float y_crossing, step, sign, area;
10177  /* covers 2+ pixels */
10178  if (x_top > x_bottom)
10179  {
10180  /* flip scanline vertically; signed area is the same */
10181  float t;
10182  y0 = y_bottom - (y0 - y_top);
10183  y1 = y_bottom - (y1 - y_top);
10184  t = y0; y0 = y1; y1 = t;
10185  t = x_bottom; x_bottom = x_top; x_top = t;
10186  dx = -dx;
10187  dy = -dy;
10188  t = x0; x0 = xb; xb = t;
10189  }
10190 
10191  x1 = (int) x_top;
10192  x2 = (int) x_bottom;
10193  /* compute intersection with y axis at x1+1 */
10194  y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top;
10195 
10196  sign = e->direction;
10197  /* area of the rectangle covered from y0..y_crossing */
10198  area = sign * (y_crossing-y0);
10199  /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */
10200  scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f);
10201 
10202  step = sign * dy;
10203  for (x = x1+1; x < x2; ++x) {
10204  scanline[x] += area + step/2;
10205  area += step;
10206  }
10207  y_crossing += (float)dy * (float)(x2 - (x1+1));
10208 
10209  scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing);
10210  scanline_fill[x2] += sign * (y1-y0);
10211  }
10212  }
10213  else
10214  {
10215  /* if edge goes outside of box we're drawing, we require */
10216  /* clipping logic. since this does not match the intended use */
10217  /* of this library, we use a different, very slow brute */
10218  /* force implementation */
10219  int x;
10220  for (x=0; x < len; ++x)
10221  {
10222  /* cases: */
10223  /* */
10224  /* there can be up to two intersections with the pixel. any intersection */
10225  /* with left or right edges can be handled by splitting into two (or three) */
10226  /* regions. intersections with top & bottom do not necessitate case-wise logic. */
10227  /* */
10228  /* the old way of doing this found the intersections with the left & right edges, */
10229  /* then used some simple logic to produce up to three segments in sorted order */
10230  /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
10231  /* across the x border, then the corresponding y position might not be distinct */
10232  /* from the other y segment, and it might ignored as an empty segment. to avoid */
10233  /* that, we need to explicitly produce segments based on x positions. */
10234 
10235  /* rename variables to clear pairs */
10236  float ya = y_top;
10237  float x1 = (float) (x);
10238  float x2 = (float) (x+1);
10239  float x3 = xb;
10240  float y3 = y_bottom;
10241  float yb,y2;
10242 
10243  yb = ((float)x - x0) / dx + y_top;
10244  y2 = ((float)x+1 - x0) / dx + y_top;
10245 
10246  if (x0 < x1 && x3 > x2) { /* three segments descending down-right */
10247  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10248  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2);
10249  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10250  } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */
10251  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10252  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb);
10253  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10254  } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */
10255  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10256  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10257  } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */
10258  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10259  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10260  } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */
10261  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10262  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10263  } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */
10264  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10265  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10266  } else { /* one segment */
10267  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3);
10268  }
10269  }
10270  }
10271  }
10272  e = e->next;
10273  }
10274 }
10275 
10276 /* directly AA rasterize edges w/o supersampling */
10277 NK_INTERN void
10278 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e,
10279  int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc)
10280 {
10281  struct nk_tt__hheap hh;
10282  struct nk_tt__active_edge *active = 0;
10283  int y,j=0, i;
10284  float scanline_data[129], *scanline, *scanline2;
10285 
10286  NK_UNUSED(vsubsample);
10287  nk_zero_struct(hh);
10288  hh.alloc = *alloc;
10289 
10290  if (result->w > 64)
10291  scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float));
10292  else scanline = scanline_data;
10293 
10294  scanline2 = scanline + result->w;
10295  y = off_y;
10296  e[n].y0 = (float) (off_y + result->h) + 1;
10297 
10298  while (j < result->h)
10299  {
10300  /* find center of pixel for this scanline */
10301  float scan_y_top = (float)y + 0.0f;
10302  float scan_y_bottom = (float)y + 1.0f;
10303  struct nk_tt__active_edge **step = &active;
10304 
10305  NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0]));
10306  NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0]));
10307 
10308  /* update all active edges; */
10309  /* remove all active edges that terminate before the top of this scanline */
10310  while (*step) {
10311  struct nk_tt__active_edge * z = *step;
10312  if (z->ey <= scan_y_top) {
10313  *step = z->next; /* delete from list */
10314  NK_ASSERT(z->direction);
10315  z->direction = 0;
10316  nk_tt__hheap_free(&hh, z);
10317  } else {
10318  step = &((*step)->next); /* advance through list */
10319  }
10320  }
10321 
10322  /* insert all edges that start before the bottom of this scanline */
10323  while (e->y0 <= scan_y_bottom) {
10324  if (e->y0 != e->y1) {
10325  struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top);
10326  if (z != 0) {
10327  NK_ASSERT(z->ey >= scan_y_top);
10328  /* insert at front */
10329  z->next = active;
10330  active = z;
10331  }
10332  }
10333  ++e;
10334  }
10335 
10336  /* now process all active edges */
10337  if (active)
10338  nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
10339 
10340  {
10341  float sum = 0;
10342  for (i=0; i < result->w; ++i) {
10343  float k;
10344  int m;
10345  sum += scanline2[i];
10346  k = scanline[i] + sum;
10347  k = (float) NK_ABS(k) * 255.0f + 0.5f;
10348  m = (int) k;
10349  if (m > 255) m = 255;
10350  result->pixels[j*result->stride + i] = (unsigned char) m;
10351  }
10352  }
10353  /* advance all the edges */
10354  step = &active;
10355  while (*step) {
10356  struct nk_tt__active_edge *z = *step;
10357  z->fx += z->fdx; /* advance to position for current scanline */
10358  step = &((*step)->next); /* advance through list */
10359  }
10360  ++y;
10361  ++j;
10362  }
10363  nk_tt__hheap_cleanup(&hh);
10364  if (scanline != scanline_data)
10365  alloc->free(alloc->userdata, scanline);
10366 }
10367 
10368 #define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0)
10369 NK_INTERN void
10370 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n)
10371 {
10372  int i,j;
10373  for (i=1; i < n; ++i) {
10374  struct nk_tt__edge t = p[i], *a = &t;
10375  j = i;
10376  while (j > 0) {
10377  struct nk_tt__edge *b = &p[j-1];
10378  int c = NK_TT__COMPARE(a,b);
10379  if (!c) break;
10380  p[j] = p[j-1];
10381  --j;
10382  }
10383  if (i != j)
10384  p[j] = t;
10385  }
10386 }
10387 
10388 NK_INTERN void
10389 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n)
10390 {
10391  /* threshold for transitioning to insertion sort */
10392  while (n > 12) {
10393  struct nk_tt__edge t;
10394  int c01,c12,c,m,i,j;
10395 
10396  /* compute median of three */
10397  m = n >> 1;
10398  c01 = NK_TT__COMPARE(&p[0],&p[m]);
10399  c12 = NK_TT__COMPARE(&p[m],&p[n-1]);
10400 
10401  /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
10402  if (c01 != c12) {
10403  /* otherwise, we'll need to swap something else to middle */
10404  int z;
10405  c = NK_TT__COMPARE(&p[0],&p[n-1]);
10406  /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
10407  /* 0<mid && mid>n: 0>n => 0; 0<n => n */
10408  z = (c == c12) ? 0 : n-1;
10409  t = p[z];
10410  p[z] = p[m];
10411  p[m] = t;
10412  }
10413 
10414  /* now p[m] is the median-of-three */
10415  /* swap it to the beginning so it won't move around */
10416  t = p[0];
10417  p[0] = p[m];
10418  p[m] = t;
10419 
10420  /* partition loop */
10421  i=1;
10422  j=n-1;
10423  for(;;) {
10424  /* handling of equality is crucial here */
10425  /* for sentinels & efficiency with duplicates */
10426  for (;;++i) {
10427  if (!NK_TT__COMPARE(&p[i], &p[0])) break;
10428  }
10429  for (;;--j) {
10430  if (!NK_TT__COMPARE(&p[0], &p[j])) break;
10431  }
10432 
10433  /* make sure we haven't crossed */
10434  if (i >= j) break;
10435  t = p[i];
10436  p[i] = p[j];
10437  p[j] = t;
10438 
10439  ++i;
10440  --j;
10441 
10442  }
10443 
10444  /* recurse on smaller side, iterate on larger */
10445  if (j < (n-i)) {
10446  nk_tt__sort_edges_quicksort(p,j);
10447  p = p+i;
10448  n = n-i;
10449  } else {
10450  nk_tt__sort_edges_quicksort(p+i, n-i);
10451  n = j;
10452  }
10453  }
10454 }
10455 
10456 NK_INTERN void
10457 nk_tt__sort_edges(struct nk_tt__edge *p, int n)
10458 {
10459  nk_tt__sort_edges_quicksort(p, n);
10460  nk_tt__sort_edges_ins_sort(p, n);
10461 }
10462 
10463 NK_INTERN void
10464 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts,
10465  int *wcount, int windings, float scale_x, float scale_y,
10466  float shift_x, float shift_y, int off_x, int off_y, int invert,
10467  struct nk_allocator *alloc)
10468 {
10469  float y_scale_inv = invert ? -scale_y : scale_y;
10470  struct nk_tt__edge *e;
10471  int n,i,j,k,m;
10472  int vsubsample = 1;
10473  /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
10474 
10475  /* now we have to blow out the windings into explicit edge lists */
10476  n = 0;
10477  for (i=0; i < windings; ++i)
10478  n += wcount[i];
10479 
10480  e = (struct nk_tt__edge*)
10481  alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1)));
10482  if (e == 0) return;
10483  n = 0;
10484 
10485  m=0;
10486  for (i=0; i < windings; ++i)
10487  {
10488  struct nk_tt__point *p = pts + m;
10489  m += wcount[i];
10490  j = wcount[i]-1;
10491  for (k=0; k < wcount[i]; j=k++) {
10492  int a=k,b=j;
10493  /* skip the edge if horizontal */
10494  if (p[j].y == p[k].y)
10495  continue;
10496 
10497  /* add edge from j to k to the list */
10498  e[n].invert = 0;
10499  if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
10500  e[n].invert = 1;
10501  a=j,b=k;
10502  }
10503  e[n].x0 = p[a].x * scale_x + shift_x;
10504  e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample;
10505  e[n].x1 = p[b].x * scale_x + shift_x;
10506  e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample;
10507  ++n;
10508  }
10509  }
10510 
10511  /* now sort the edges by their highest point (should snap to integer, and then by x) */
10512  /*STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); */
10513  nk_tt__sort_edges(e, n);
10514  /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
10515  nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc);
10516  alloc->free(alloc->userdata, e);
10517 }
10518 
10519 NK_INTERN void
10520 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y)
10521 {
10522  if (!points) return; /* during first pass, it's unallocated */
10523  points[n].x = x;
10524  points[n].y = y;
10525 }
10526 
10527 NK_INTERN int
10528 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points,
10529  float x0, float y0, float x1, float y1, float x2, float y2,
10530  float objspace_flatness_squared, int n)
10531 {
10532  /* tesselate until threshold p is happy...
10533  * @TODO warped to compensate for non-linear stretching */
10534  /* midpoint */
10535  float mx = (x0 + 2*x1 + x2)/4;
10536  float my = (y0 + 2*y1 + y2)/4;
10537  /* versus directly drawn line */
10538  float dx = (x0+x2)/2 - mx;
10539  float dy = (y0+y2)/2 - my;
10540  if (n > 16) /* 65536 segments on one curve better be enough! */
10541  return 1;
10542 
10543  /* half-pixel error allowed... need to be smaller if AA */
10544  if (dx*dx+dy*dy > objspace_flatness_squared) {
10545  nk_tt__tesselate_curve(points, num_points, x0,y0,
10546  (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
10547  nk_tt__tesselate_curve(points, num_points, mx,my,
10548  (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
10549  } else {
10550  nk_tt__add_point(points, *num_points,x2,y2);
10551  *num_points = *num_points+1;
10552  }
10553  return 1;
10554 }
10555 
10556 /* returns number of contours */
10557 NK_INTERN struct nk_tt__point*
10558 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts,
10559  float objspace_flatness, int **contour_lengths, int *num_contours,
10560  struct nk_allocator *alloc)
10561 {
10562  struct nk_tt__point *points=0;
10563  int num_points=0;
10564  float objspace_flatness_squared = objspace_flatness * objspace_flatness;
10565  int i;
10566  int n=0;
10567  int start=0;
10568  int pass;
10569 
10570  /* count how many "moves" there are to get the contour count */
10571  for (i=0; i < num_verts; ++i)
10572  if (vertices[i].type == NK_TT_vmove) ++n;
10573 
10574  *num_contours = n;
10575  if (n == 0) return 0;
10576 
10577  *contour_lengths = (int *)
10578  alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n));
10579  if (*contour_lengths == 0) {
10580  *num_contours = 0;
10581  return 0;
10582  }
10583 
10584  /* make two passes through the points so we don't need to realloc */
10585  for (pass=0; pass < 2; ++pass)
10586  {
10587  float x=0,y=0;
10588  if (pass == 1) {
10589  points = (struct nk_tt__point *)
10590  alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0]));
10591  if (points == 0) goto error;
10592  }
10593  num_points = 0;
10594  n= -1;
10595 
10596  for (i=0; i < num_verts; ++i)
10597  {
10598  switch (vertices[i].type) {
10599  case NK_TT_vmove:
10600  /* start the next contour */
10601  if (n >= 0)
10602  (*contour_lengths)[n] = num_points - start;
10603  ++n;
10604  start = num_points;
10605 
10606  x = vertices[i].x, y = vertices[i].y;
10607  nk_tt__add_point(points, num_points++, x,y);
10608  break;
10609  case NK_TT_vline:
10610  x = vertices[i].x, y = vertices[i].y;
10611  nk_tt__add_point(points, num_points++, x, y);
10612  break;
10613  case NK_TT_vcurve:
10614  nk_tt__tesselate_curve(points, &num_points, x,y,
10615  vertices[i].cx, vertices[i].cy,
10616  vertices[i].x, vertices[i].y,
10617  objspace_flatness_squared, 0);
10618  x = vertices[i].x, y = vertices[i].y;
10619  break;
10620  default: break;
10621  }
10622  }
10623  (*contour_lengths)[n] = num_points - start;
10624  }
10625  return points;
10626 
10627 error:
10628  alloc->free(alloc->userdata, points);
10629  alloc->free(alloc->userdata, *contour_lengths);
10630  *contour_lengths = 0;
10631  *num_contours = 0;
10632  return 0;
10633 }
10634 
10635 NK_INTERN void
10636 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels,
10637  struct nk_tt_vertex *vertices, int num_verts,
10638  float scale_x, float scale_y, float shift_x, float shift_y,
10639  int x_off, int y_off, int invert, struct nk_allocator *alloc)
10640 {
10641  float scale = scale_x > scale_y ? scale_y : scale_x;
10642  int winding_count, *winding_lengths;
10643  struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts,
10644  flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc);
10645 
10646  NK_ASSERT(alloc);
10647  if (windings) {
10648  nk_tt__rasterize(result, windings, winding_lengths, winding_count,
10649  scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc);
10650  alloc->free(alloc->userdata, winding_lengths);
10651  alloc->free(alloc->userdata, windings);
10652  }
10653 }
10654 
10655 NK_INTERN void
10656 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output,
10657  int out_w, int out_h, int out_stride, float scale_x, float scale_y,
10658  float shift_x, float shift_y, int glyph, struct nk_allocator *alloc)
10659 {
10660  int ix0,iy0;
10661  struct nk_tt_vertex *vertices;
10662  int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices);
10663  struct nk_tt__bitmap gbm;
10664 
10665  nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x,
10666  shift_y, &ix0,&iy0,0,0);
10667  gbm.pixels = output;
10668  gbm.w = out_w;
10669  gbm.h = out_h;
10670  gbm.stride = out_stride;
10671 
10672  if (gbm.w && gbm.h)
10673  nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y,
10674  shift_x, shift_y, ix0,iy0, 1, alloc);
10675  alloc->free(alloc->userdata, vertices);
10676 }
10677 
10678 /*-------------------------------------------------------------
10679  * Bitmap baking
10680  * --------------------------------------------------------------*/
10681 NK_INTERN int
10682 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels,
10683  int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc)
10684 {
10685  int num_nodes = pw - padding;
10686  struct nk_rp_context *context = (struct nk_rp_context *)
10687  alloc->alloc(alloc->userdata,0, sizeof(*context));
10688  struct nk_rp_node *nodes = (struct nk_rp_node*)
10689  alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes));
10690 
10691  if (context == 0 || nodes == 0) {
10692  if (context != 0) alloc->free(alloc->userdata, context);
10693  if (nodes != 0) alloc->free(alloc->userdata, nodes);
10694  return 0;
10695  }
10696 
10697  spc->width = pw;
10698  spc->height = ph;
10699  spc->pixels = pixels;
10700  spc->pack_info = context;
10701  spc->nodes = nodes;
10702  spc->padding = padding;
10703  spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw;
10704  spc->h_oversample = 1;
10705  spc->v_oversample = 1;
10706 
10707  nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
10708  if (pixels)
10709  NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */
10710  return 1;
10711 }
10712 
10713 NK_INTERN void
10714 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc)
10715 {
10716  alloc->free(alloc->userdata, spc->nodes);
10717  alloc->free(alloc->userdata, spc->pack_info);
10718 }
10719 
10720 NK_INTERN void
10721 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc,
10722  unsigned int h_oversample, unsigned int v_oversample)
10723 {
10724  NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE);
10725  NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE);
10726  if (h_oversample <= NK_TT_MAX_OVERSAMPLE)
10727  spc->h_oversample = h_oversample;
10728  if (v_oversample <= NK_TT_MAX_OVERSAMPLE)
10729  spc->v_oversample = v_oversample;
10730 }
10731 
10732 NK_INTERN void
10733 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
10734  int kernel_width)
10735 {
10736  unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
10737  int safe_w = w - kernel_width;
10738  int j;
10739 
10740  for (j=0; j < h; ++j)
10741  {
10742  int i;
10743  unsigned int total;
10744  NK_MEMSET(buffer, 0, (nk_size)kernel_width);
10745 
10746  total = 0;
10747 
10748  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
10749  switch (kernel_width) {
10750  case 2:
10751  for (i=0; i <= safe_w; ++i) {
10752  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10753  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10754  pixels[i] = (unsigned char) (total / 2);
10755  }
10756  break;
10757  case 3:
10758  for (i=0; i <= safe_w; ++i) {
10759  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10760  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10761  pixels[i] = (unsigned char) (total / 3);
10762  }
10763  break;
10764  case 4:
10765  for (i=0; i <= safe_w; ++i) {
10766  total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK];
10767  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10768  pixels[i] = (unsigned char) (total / 4);
10769  }
10770  break;
10771  case 5:
10772  for (i=0; i <= safe_w; ++i) {
10773  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10774  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10775  pixels[i] = (unsigned char) (total / 5);
10776  }
10777  break;
10778  default:
10779  for (i=0; i <= safe_w; ++i) {
10780  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10781  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10782  pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
10783  }
10784  break;
10785  }
10786 
10787  for (; i < w; ++i) {
10788  NK_ASSERT(pixels[i] == 0);
10789  total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
10790  pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
10791  }
10792  pixels += stride_in_bytes;
10793  }
10794 }
10795 
10796 NK_INTERN void
10797 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
10798  int kernel_width)
10799 {
10800  unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
10801  int safe_h = h - kernel_width;
10802  int j;
10803 
10804  for (j=0; j < w; ++j)
10805  {
10806  int i;
10807  unsigned int total;
10808  NK_MEMSET(buffer, 0, (nk_size)kernel_width);
10809 
10810  total = 0;
10811 
10812  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
10813  switch (kernel_width) {
10814  case 2:
10815  for (i=0; i <= safe_h; ++i) {
10816  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10817  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10818  pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
10819  }
10820  break;
10821  case 3:
10822  for (i=0; i <= safe_h; ++i) {
10823  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10824  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10825  pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
10826  }
10827  break;
10828  case 4:
10829  for (i=0; i <= safe_h; ++i) {
10830  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10831  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10832  pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
10833  }
10834  break;
10835  case 5:
10836  for (i=0; i <= safe_h; ++i) {
10837  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10838  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10839  pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
10840  }
10841  break;
10842  default:
10843  for (i=0; i <= safe_h; ++i) {
10844  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10845  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10846  pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
10847  }
10848  break;
10849  }
10850 
10851  for (; i < h; ++i) {
10852  NK_ASSERT(pixels[i*stride_in_bytes] == 0);
10853  total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
10854  pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
10855  }
10856  pixels += 1;
10857  }
10858 }
10859 
10860 NK_INTERN float
10861 nk_tt__oversample_shift(int oversample)
10862 {
10863  if (!oversample)
10864  return 0.0f;
10865 
10866  /* The prefilter is a box filter of width "oversample", */
10867  /* which shifts phase by (oversample - 1)/2 pixels in */
10868  /* oversampled space. We want to shift in the opposite */
10869  /* direction to counter this. */
10870  return (float)-(oversample - 1) / (2.0f * (float)oversample);
10871 }
10872 
10873 /* rects array must be big enough to accommodate all characters in the given ranges */
10874 NK_INTERN int
10875 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc,
10876  struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
10877  int num_ranges, struct nk_rp_rect *rects)
10878 {
10879  int i,j,k;
10880  k = 0;
10881 
10882  for (i=0; i < num_ranges; ++i) {
10883  float fh = ranges[i].font_size;
10884  float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh):
10885  nk_tt_ScaleForMappingEmToPixels(info, -fh);
10886  ranges[i].h_oversample = (unsigned char) spc->h_oversample;
10887  ranges[i].v_oversample = (unsigned char) spc->v_oversample;
10888  for (j=0; j < ranges[i].num_chars; ++j) {
10889  int x0,y0,x1,y1;
10890  int codepoint = ranges[i].first_unicode_codepoint_in_range ?
10891  ranges[i].first_unicode_codepoint_in_range + j :
10892  ranges[i].array_of_unicode_codepoints[j];
10893 
10894  int glyph = nk_tt_FindGlyphIndex(info, codepoint);
10895  nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample,
10896  scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1);
10897  rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1);
10898  rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1);
10899  ++k;
10900  }
10901  }
10902  return k;
10903 }
10904 
10905 NK_INTERN int
10906 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc,
10907  struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
10908  int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc)
10909 {
10910  int i,j,k, return_value = 1;
10911  /* save current values */
10912  int old_h_over = (int)spc->h_oversample;
10913  int old_v_over = (int)spc->v_oversample;
10914  /* rects array must be big enough to accommodate all characters in the given ranges */
10915 
10916  k = 0;
10917  for (i=0; i < num_ranges; ++i)
10918  {
10919  float fh = ranges[i].font_size;
10920  float recip_h,recip_v,sub_x,sub_y;
10921  float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh):
10922  nk_tt_ScaleForMappingEmToPixels(info, -fh);
10923 
10924  spc->h_oversample = ranges[i].h_oversample;
10925  spc->v_oversample = ranges[i].v_oversample;
10926 
10927  recip_h = 1.0f / (float)spc->h_oversample;
10928  recip_v = 1.0f / (float)spc->v_oversample;
10929 
10930  sub_x = nk_tt__oversample_shift((int)spc->h_oversample);
10931  sub_y = nk_tt__oversample_shift((int)spc->v_oversample);
10932 
10933  for (j=0; j < ranges[i].num_chars; ++j)
10934  {
10935  struct nk_rp_rect *r = &rects[k];
10936  if (r->was_packed)
10937  {
10938  struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j];
10939  int advance, lsb, x0,y0,x1,y1;
10940  int codepoint = ranges[i].first_unicode_codepoint_in_range ?
10941  ranges[i].first_unicode_codepoint_in_range + j :
10942  ranges[i].array_of_unicode_codepoints[j];
10943  int glyph = nk_tt_FindGlyphIndex(info, codepoint);
10944  nk_rp_coord pad = (nk_rp_coord) spc->padding;
10945 
10946  /* pad on left and top */
10947  r->x = (nk_rp_coord)((int)r->x + (int)pad);
10948  r->y = (nk_rp_coord)((int)r->y + (int)pad);
10949  r->w = (nk_rp_coord)((int)r->w - (int)pad);
10950  r->h = (nk_rp_coord)((int)r->h - (int)pad);
10951 
10952  nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
10953  nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample,
10954  (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1);
10955  nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes,
10956  (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1),
10957  spc->stride_in_bytes, scale * (float)spc->h_oversample,
10958  scale * (float)spc->v_oversample, 0,0, glyph, alloc);
10959 
10960  if (spc->h_oversample > 1)
10961  nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
10962  r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample);
10963 
10964  if (spc->v_oversample > 1)
10965  nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
10966  r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample);
10967 
10968  bc->x0 = (nk_ushort) r->x;
10969  bc->y0 = (nk_ushort) r->y;
10970  bc->x1 = (nk_ushort) (r->x + r->w);
10971  bc->y1 = (nk_ushort) (r->y + r->h);
10972  bc->xadvance = scale * (float)advance;
10973  bc->xoff = (float) x0 * recip_h + sub_x;
10974  bc->yoff = (float) y0 * recip_v + sub_y;
10975  bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x;
10976  bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y;
10977  } else {
10978  return_value = 0; /* if any fail, report failure */
10979  }
10980  ++k;
10981  }
10982  }
10983  /* restore original values */
10984  spc->h_oversample = (unsigned int)old_h_over;
10985  spc->v_oversample = (unsigned int)old_v_over;
10986  return return_value;
10987 }
10988 
10989 NK_INTERN void
10990 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph,
10991  int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q,
10992  int align_to_integer)
10993 {
10994  float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph;
10995  struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index);
10996  if (align_to_integer) {
10997  int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f);
10998  int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f);
10999 
11000  float x = (float)tx;
11001  float y = (float)ty;
11002 
11003  q->x0 = x;
11004  q->y0 = y;
11005  q->x1 = x + b->xoff2 - b->xoff;
11006  q->y1 = y + b->yoff2 - b->yoff;
11007  } else {
11008  q->x0 = *xpos + b->xoff;
11009  q->y0 = *ypos + b->yoff;
11010  q->x1 = *xpos + b->xoff2;
11011  q->y1 = *ypos + b->yoff2;
11012  }
11013  q->s0 = b->x0 * ipw;
11014  q->t0 = b->y0 * iph;
11015  q->s1 = b->x1 * ipw;
11016  q->t1 = b->y1 * iph;
11017  *xpos += b->xadvance;
11018 }
11019 
11020 /* -------------------------------------------------------------
11021  *
11022  * FONT BAKING
11023  *
11024  * --------------------------------------------------------------*/
11025 struct nk_font_bake_data {
11026  struct nk_tt_fontinfo info;
11027  struct nk_rp_rect *rects;
11028  struct nk_tt_pack_range *ranges;
11029  nk_rune range_count;
11030 };
11031 
11032 struct nk_font_baker {
11033  struct nk_allocator alloc;
11034  struct nk_tt_pack_context spc;
11035  struct nk_font_bake_data *build;
11036  struct nk_tt_packedchar *packed_chars;
11037  struct nk_rp_rect *rects;
11038  struct nk_tt_pack_range *ranges;
11039 };
11040 
11041 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect);
11042 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range);
11043 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar);
11044 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
11045 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
11046 
11047 NK_INTERN int
11048 nk_range_count(const nk_rune *range)
11049 {
11050  const nk_rune *iter = range;
11051  NK_ASSERT(range);
11052  if (!range) return 0;
11053  while (*(iter++) != 0);
11054  return (iter == range) ? 0 : (int)((iter - range)/2);
11055 }
11056 
11057 NK_INTERN int
11058 nk_range_glyph_count(const nk_rune *range, int count)
11059 {
11060  int i = 0;
11061  int total_glyphs = 0;
11062  for (i = 0; i < count; ++i) {
11063  int diff;
11064  nk_rune f = range[(i*2)+0];
11065  nk_rune t = range[(i*2)+1];
11066  NK_ASSERT(t >= f);
11067  diff = (int)((t - f) + 1);
11068  total_glyphs += diff;
11069  }
11070  return total_glyphs;
11071 }
11072 
11073 NK_API const nk_rune*
11074 nk_font_default_glyph_ranges(void)
11075 {
11076  NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
11077  return ranges;
11078 }
11079 
11080 NK_API const nk_rune*
11081 nk_font_chinese_glyph_ranges(void)
11082 {
11083  NK_STORAGE const nk_rune ranges[] = {
11084  0x0020, 0x00FF,
11085  0x3000, 0x30FF,
11086  0x31F0, 0x31FF,
11087  0xFF00, 0xFFEF,
11088  0x4e00, 0x9FAF,
11089  0
11090  };
11091  return ranges;
11092 }
11093 
11094 NK_API const nk_rune*
11095 nk_font_cyrillic_glyph_ranges(void)
11096 {
11097  NK_STORAGE const nk_rune ranges[] = {
11098  0x0020, 0x00FF,
11099  0x0400, 0x052F,
11100  0x2DE0, 0x2DFF,
11101  0xA640, 0xA69F,
11102  0
11103  };
11104  return ranges;
11105 }
11106 
11107 NK_API const nk_rune*
11108 nk_font_korean_glyph_ranges(void)
11109 {
11110  NK_STORAGE const nk_rune ranges[] = {
11111  0x0020, 0x00FF,
11112  0x3131, 0x3163,
11113  0xAC00, 0xD79D,
11114  0
11115  };
11116  return ranges;
11117 }
11118 
11119 NK_INTERN void
11120 nk_font_baker_memory(nk_size *temp, int *glyph_count,
11121  struct nk_font_config *config_list, int count)
11122 {
11123  int range_count = 0;
11124  int total_range_count = 0;
11125  struct nk_font_config *iter;
11126 
11127  NK_ASSERT(config_list);
11128  NK_ASSERT(glyph_count);
11129  if (!config_list) {
11130  *temp = 0;
11131  *glyph_count = 0;
11132  return;
11133  }
11134 
11135  *glyph_count = 0;
11136  if (!config_list->range)
11137  config_list->range = nk_font_default_glyph_ranges();
11138  for (iter = config_list; iter; iter = iter->next) {
11139  range_count = nk_range_count(iter->range);
11140  total_range_count += range_count;
11141  *glyph_count += nk_range_glyph_count(iter->range, range_count);
11142  }
11143 
11144  *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect);
11145  *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range);
11146  *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar);
11147  *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
11148  *temp += sizeof(struct nk_font_baker);
11149  *temp += nk_rect_align + nk_range_align + nk_char_align;
11150  *temp += nk_build_align + nk_baker_align;
11151 }
11152 
11153 NK_INTERN struct nk_font_baker*
11154 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
11155 {
11156  struct nk_font_baker *baker;
11157  if (!memory) return 0;
11158  /* setup baker inside a memory block */
11159  baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
11160  baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
11161  baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
11162  baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
11163  baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
11164  baker->alloc = *alloc;
11165  return baker;
11166 }
11167 
11168 NK_INTERN int
11169 nk_font_bake_pack(struct nk_font_baker *baker,
11170  nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
11171  const struct nk_font_config *config_list, int count,
11172  struct nk_allocator *alloc)
11173 {
11174  NK_STORAGE const nk_size max_height = 1024 * 32;
11175  const struct nk_font_config *config_iter;
11176  int total_glyph_count = 0;
11177  int total_range_count = 0;
11178  int range_count = 0;
11179  int i = 0;
11180 
11181  NK_ASSERT(image_memory);
11182  NK_ASSERT(width);
11183  NK_ASSERT(height);
11184  NK_ASSERT(config_list);
11185  NK_ASSERT(count);
11186  NK_ASSERT(alloc);
11187 
11188  if (!image_memory || !width || !height || !config_list || !count) return nk_false;
11189  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
11190  range_count = nk_range_count(config_iter->range);
11191  total_range_count += range_count;
11192  total_glyph_count += nk_range_glyph_count(config_iter->range, range_count);
11193  }
11194 
11195  /* setup font baker from temporary memory */
11196  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
11197  const struct nk_font_config *cfg = config_iter;
11198  if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)cfg->ttf_blob, 0))
11199  return nk_false;
11200  }
11201 
11202  *height = 0;
11203  *width = (total_glyph_count > 1000) ? 1024 : 512;
11204  nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
11205  {
11206  int input_i = 0;
11207  int range_n = 0;
11208  int rect_n = 0;
11209  int char_n = 0;
11210 
11211  if (custom) {
11212  /* pack custom user data first so it will be in the upper left corner*/
11213  struct nk_rp_rect custom_space;
11214  nk_zero(&custom_space, sizeof(custom_space));
11215  custom_space.w = (nk_rp_coord)((custom->w * 2) + 1);
11216  custom_space.h = (nk_rp_coord)(custom->h + 1);
11217 
11218  nk_tt_PackSetOversampling(&baker->spc, 1, 1);
11219  nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1);
11220  *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
11221 
11222  custom->x = (short)custom_space.x;
11223  custom->y = (short)custom_space.y;
11224  custom->w = (short)custom_space.w;
11225  custom->h = (short)custom_space.h;
11226  }
11227 
11228  /* first font pass: pack all glyphs */
11229  for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
11230  input_i++, config_iter = config_iter->next)
11231  {
11232  int n = 0;
11233  int glyph_count;
11234  const nk_rune *in_range;
11235  const struct nk_font_config *cfg = config_iter;
11236  struct nk_font_bake_data *tmp = &baker->build[input_i];
11237 
11238  /* count glyphs + ranges in current font */
11239  glyph_count = 0; range_count = 0;
11240  for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
11241  glyph_count += (int)(in_range[1] - in_range[0]) + 1;
11242  range_count++;
11243  }
11244 
11245  /* setup ranges */
11246  tmp->ranges = baker->ranges + range_n;
11247  tmp->range_count = (nk_rune)range_count;
11248  range_n += range_count;
11249  for (i = 0; i < range_count; ++i) {
11250  in_range = &cfg->range[i * 2];
11251  tmp->ranges[i].font_size = cfg->size;
11252  tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
11253  tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
11254  tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
11255  char_n += tmp->ranges[i].num_chars;
11256  }
11257 
11258  /* pack */
11259  tmp->rects = baker->rects + rect_n;
11260  rect_n += glyph_count;
11261  nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
11262  n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
11263  tmp->ranges, (int)tmp->range_count, tmp->rects);
11264  nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n);
11265 
11266  /* texture height */
11267  for (i = 0; i < n; ++i) {
11268  if (tmp->rects[i].was_packed)
11269  *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
11270  }
11271  }
11272  NK_ASSERT(rect_n == total_glyph_count);
11273  NK_ASSERT(char_n == total_glyph_count);
11274  NK_ASSERT(range_n == total_range_count);
11275  }
11276  *height = (int)nk_round_up_pow2((nk_uint)*height);
11277  *image_memory = (nk_size)(*width) * (nk_size)(*height);
11278  return nk_true;
11279 }
11280 
11281 NK_INTERN void
11282 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
11283  struct nk_font_glyph *glyphs, int glyphs_count,
11284  const struct nk_font_config *config_list, int font_count)
11285 {
11286  int input_i = 0;
11287  nk_rune glyph_n = 0;
11288  const struct nk_font_config *config_iter;
11289 
11290  NK_ASSERT(image_memory);
11291  NK_ASSERT(width);
11292  NK_ASSERT(height);
11293  NK_ASSERT(config_list);
11294  NK_ASSERT(baker);
11295  NK_ASSERT(font_count);
11296  NK_ASSERT(glyphs_count);
11297  if (!image_memory || !width || !height || !config_list ||
11298  !font_count || !glyphs || !glyphs_count)
11299  return;
11300 
11301  /* second font pass: render glyphs */
11302  nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
11303  baker->spc.pixels = (unsigned char*)image_memory;
11304  baker->spc.height = (int)height;
11305  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
11306  ++input_i, config_iter = config_iter->next)
11307  {
11308  const struct nk_font_config *cfg = config_iter;
11309  struct nk_font_bake_data *tmp = &baker->build[input_i];
11310  nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
11311  nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges,
11312  (int)tmp->range_count, tmp->rects, &baker->alloc);
11313  }
11314  nk_tt_PackEnd(&baker->spc, &baker->alloc);
11315 
11316  /* third pass: setup font and glyphs */
11317  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
11318  ++input_i, config_iter = config_iter->next)
11319  {
11320  nk_size i = 0;
11321  int char_idx = 0;
11322  nk_rune glyph_count = 0;
11323  const struct nk_font_config *cfg = config_iter;
11324  struct nk_font_bake_data *tmp = &baker->build[input_i];
11325  struct nk_baked_font *dst_font = cfg->font;
11326 
11327  float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size);
11328  int unscaled_ascent, unscaled_descent, unscaled_line_gap;
11329  nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
11330  &unscaled_line_gap);
11331 
11332  /* fill baked font */
11333  if (!cfg->merge_mode) {
11334  dst_font->ranges = cfg->range;
11335  dst_font->height = cfg->size;
11336  dst_font->ascent = ((float)unscaled_ascent * font_scale);
11337  dst_font->descent = ((float)unscaled_descent * font_scale);
11338  dst_font->glyph_offset = glyph_n;
11339  }
11340 
11341  /* fill own baked font glyph array */
11342  for (i = 0; i < tmp->range_count; ++i)
11343  {
11344  struct nk_tt_pack_range *range = &tmp->ranges[i];
11345  for (char_idx = 0; char_idx < range->num_chars; char_idx++)
11346  {
11347  nk_rune codepoint = 0;
11348  float dummy_x = 0, dummy_y = 0;
11349  struct nk_tt_aligned_quad q;
11350  struct nk_font_glyph *glyph;
11351 
11352  /* query glyph bounds from stb_truetype */
11353  const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx];
11354  if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue;
11355  codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
11356  nk_tt_GetPackedQuad(range->chardata_for_range, (int)width,
11357  (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
11358 
11359  /* fill own glyph type with data */
11360  glyph = &glyphs[dst_font->glyph_offset + (unsigned int)glyph_count];
11361  glyph->codepoint = codepoint;
11362  glyph->x0 = q.x0; glyph->y0 = q.y0;
11363  glyph->x1 = q.x1; glyph->y1 = q.y1;
11364  glyph->y0 += (dst_font->ascent + 0.5f);
11365  glyph->y1 += (dst_font->ascent + 0.5f);
11366  glyph->w = glyph->x1 - glyph->x0 + 0.5f;
11367  glyph->h = glyph->y1 - glyph->y0;
11368 
11369  if (cfg->coord_type == NK_COORD_PIXEL) {
11370  glyph->u0 = q.s0 * (float)width;
11371  glyph->v0 = q.t0 * (float)height;
11372  glyph->u1 = q.s1 * (float)width;
11373  glyph->v1 = q.t1 * (float)height;
11374  } else {
11375  glyph->u0 = q.s0;
11376  glyph->v0 = q.t0;
11377  glyph->u1 = q.s1;
11378  glyph->v1 = q.t1;
11379  }
11380  glyph->xadvance = (pc->xadvance + cfg->spacing.x);
11381  if (cfg->pixel_snap)
11382  glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
11383  glyph_count++;
11384  }
11385  }
11386  dst_font->glyph_count = glyph_count;
11387  glyph_n += dst_font->glyph_count;
11388  }
11389 }
11390 
11391 NK_INTERN void
11392 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
11393  struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
11394  int tex_height, char white, char black)
11395 {
11396  nk_byte *pixels;
11397  int y = 0;
11398  int x = 0;
11399  int n = 0;
11400 
11401  NK_ASSERT(img_memory);
11402  NK_ASSERT(img_width);
11403  NK_ASSERT(img_height);
11404  NK_ASSERT(texture_data_mask);
11405  NK_UNUSED(tex_height);
11406  if (!img_memory || !img_width || !img_height || !texture_data_mask)
11407  return;
11408 
11409  pixels = (nk_byte*)img_memory;
11410  for (y = 0, n = 0; y < tex_height; ++y) {
11411  for (x = 0; x < tex_width; ++x, ++n) {
11412  const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
11413  const int off1 = off0 + 1 + tex_width;
11414  pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
11415  pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
11416  }
11417  }
11418 }
11419 
11420 NK_INTERN void
11421 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
11422  const void *in_memory)
11423 {
11424  int n = 0;
11425  nk_rune *dst;
11426  const nk_byte *src;
11427 
11428  NK_ASSERT(out_memory);
11429  NK_ASSERT(in_memory);
11430  NK_ASSERT(img_width);
11431  NK_ASSERT(img_height);
11432  if (!out_memory || !in_memory || !img_height || !img_width) return;
11433 
11434  dst = (nk_rune*)out_memory;
11435  src = (const nk_byte*)in_memory;
11436  for (n = (int)(img_width * img_height); n > 0; n--)
11437  *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
11438 }
11439 
11440 /* -------------------------------------------------------------
11441  *
11442  * FONT
11443  *
11444  * --------------------------------------------------------------*/
11445 NK_INTERN float
11446 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
11447 {
11448  nk_rune unicode;
11449  int text_len = 0;
11450  float text_width = 0;
11451  int glyph_len = 0;
11452  float scale = 0;
11453 
11454  struct nk_font *font = (struct nk_font*)handle.ptr;
11455  NK_ASSERT(font);
11456  NK_ASSERT(font->glyphs);
11457  if (!font || !text || !len)
11458  return 0;
11459 
11460  scale = height/font->info.height;
11461  glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
11462  if (!glyph_len) return 0;
11463  while (text_len <= (int)len && glyph_len) {
11464  const struct nk_font_glyph *g;
11465  if (unicode == NK_UTF_INVALID) break;
11466 
11467  /* query currently drawn glyph information */
11468  g = nk_font_find_glyph(font, unicode);
11469  text_width += g->xadvance * scale;
11470 
11471  /* offset next glyph */
11472  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
11473  text_len += glyph_len;
11474  }
11475  return text_width;
11476 }
11477 
11478 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11479 NK_INTERN void
11480 nk_font_query_font_glyph(nk_handle handle, float height,
11481  struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
11482 {
11483  float scale;
11484  const struct nk_font_glyph *g;
11485  struct nk_font *font;
11486 
11487  NK_ASSERT(glyph);
11488  NK_UNUSED(next_codepoint);
11489 
11490  font = (struct nk_font*)handle.ptr;
11491  NK_ASSERT(font);
11492  NK_ASSERT(font->glyphs);
11493  if (!font || !glyph)
11494  return;
11495 
11496  scale = height/font->info.height;
11497  g = nk_font_find_glyph(font, codepoint);
11498  glyph->width = (g->x1 - g->x0) * scale;
11499  glyph->height = (g->y1 - g->y0) * scale;
11500  glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
11501  glyph->xadvance = (g->xadvance * scale);
11502  glyph->uv[0] = nk_vec2(g->u0, g->v0);
11503  glyph->uv[1] = nk_vec2(g->u1, g->v1);
11504 }
11505 #endif
11506 
11507 NK_API const struct nk_font_glyph*
11508 nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
11509 {
11510  int i = 0;
11511  int count;
11512  int total_glyphs = 0;
11513  const struct nk_font_glyph *glyph = 0;
11514 
11515  NK_ASSERT(font);
11516  NK_ASSERT(font->glyphs);
11517  NK_ASSERT(font->info.ranges);
11518  if (!font || !font->glyphs) return 0;
11519 
11520  glyph = font->fallback;
11521  count = nk_range_count(font->info.ranges);
11522  for (i = 0; i < count; ++i) {
11523  int diff;
11524  nk_rune f = font->info.ranges[(i*2)+0];
11525  nk_rune t = font->info.ranges[(i*2)+1];
11526  diff = (int)((t - f) + 1);
11527  if (unicode >= f && unicode <= t)
11528  return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
11529  total_glyphs += diff;
11530  }
11531  return glyph;
11532 }
11533 
11534 NK_INTERN void
11535 nk_font_init(struct nk_font *font, float pixel_height,
11536  nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
11537  const struct nk_baked_font *baked_font, nk_handle atlas)
11538 {
11539  struct nk_baked_font baked;
11540  NK_ASSERT(font);
11541  NK_ASSERT(glyphs);
11542  NK_ASSERT(baked_font);
11543  if (!font || !glyphs || !baked_font)
11544  return;
11545 
11546  baked = *baked_font;
11547  font->info = baked;
11548  font->scale = (float)pixel_height / (float)font->info.height;
11549  font->glyphs = &glyphs[baked_font->glyph_offset];
11550  font->texture = atlas;
11551  font->fallback_codepoint = fallback_codepoint;
11552  font->fallback = nk_font_find_glyph(font, fallback_codepoint);
11553 
11554  font->handle.height = font->info.height * font->scale;
11555  font->handle.width = nk_font_text_width;
11556  font->handle.userdata.ptr = font;
11557 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11558  font->handle.query = nk_font_query_font_glyph;
11559  font->handle.texture = font->texture;
11560 #endif
11561 }
11562 
11563 /* ---------------------------------------------------------------------------
11564  *
11565  * DEFAULT FONT
11566  *
11567  * ProggyClean.ttf
11568  * Copyright (c) 2004, 2005 Tristan Grimmer
11569  * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
11570  * Download and more information at http://upperbounds.net
11571  *-----------------------------------------------------------------------------*/
11572 #ifdef NK_INCLUDE_DEFAULT_FONT
11573 
11574  #ifdef __clang__
11575 #pragma clang diagnostic push
11576 
11577 #pragma clang diagnostic ignored "-Woverlength-strings"
11578 #elif defined(__GNUC__) || defined(__GNUG__)
11579 #pragma GCC diagnostic push
11580 #pragma GCC diagnostic ignored "-Woverlength-strings"
11581 #endif
11582 
11583 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
11584  "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
11585  "2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#"
11586  "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
11587  "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N"
11588  "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N"
11589  "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)"
11590  "tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX"
11591  "ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc."
11592  "x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G"
11593  "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)"
11594  "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#"
11595  "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM"
11596  "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu"
11597  "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/"
11598  "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L"
11599  "%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#"
11600  "OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)("
11601  "h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h"
11602  "o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO"
11603  "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-"
11604  "sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-"
11605  "eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO"
11606  "M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%"
11607  "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]"
11608  "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
11609  "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
11610  "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL("
11611  "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
11612  "nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?"
11613  "7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;"
11614  ")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
11615  "D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX("
11616  "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs"
11617  "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
11618  "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-"
11619  "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i"
11620  "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7"
11621  ".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@"
11622  "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*"
11623  "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u"
11624  "@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#"
11625  "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#"
11626  "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0"
11627  "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8"
11628  "6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#"
11629  "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD"
11630  ":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+"
11631  "tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*"
11632  "$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7"
11633  ":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A"
11634  "7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7"
11635  "u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT"
11636  "LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M"
11637  ":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>"
11638  "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%"
11639  "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;"
11640  "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:"
11641  "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%"
11642  "9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-"
11643  "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*"
11644  "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY"
11645  "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
11646  "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`"
11647  "0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/"
11648  "+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj"
11649  "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V"
11650  "?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK"
11651  "Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa"
11652  ">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>"
11653  "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I"
11654  "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#"
11655  "Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$"
11656  "MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)"
11657  "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo"
11658  "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P"
11659  "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO"
11660  "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#"
11661  ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>"
11662  "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#"
11663  "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4"
11664  "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#"
11665  "/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#"
11666  "m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#"
11667  "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
11668  "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
11669  "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
11670 #endif /* NK_INCLUDE_DEFAULT_FONT */
11671 
11672 #define NK_CURSOR_DATA_W 90
11673 #define NK_CURSOR_DATA_H 27
11674 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
11675 {
11676  "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX"
11677  "..- -X.....X- X.X - X.X -X.....X - X.....X"
11678  "--- -XXX.XXX- X...X - X...X -X....X - X....X"
11679  "X - X.X - X.....X - X.....X -X...X - X...X"
11680  "XX - X.X -X.......X- X.......X -X..X.X - X.X..X"
11681  "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X"
11682  "X..X - X.X - X.X - X.X -XX X.X - X.X XX"
11683  "X...X - X.X - X.X - XX X.X XX - X.X - X.X "
11684  "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X "
11685  "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X "
11686  "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X "
11687  "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X "
11688  "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X "
11689  "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X "
11690  "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X "
11691  "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X "
11692  "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX "
11693  "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------"
11694  "X.X X..X - -X.......X- X.......X - XX XX - "
11695  "XX X..X - - X.....X - X.....X - X.X X.X - "
11696  " X..X - X...X - X...X - X..X X..X - "
11697  " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - "
11698  "------------ - X - X -X.....................X- "
11699  " ----------------------------------- X...XXXXXXXXXXXXX...X - "
11700  " - X..X X..X - "
11701  " - X.X X.X - "
11702  " - XX XX - "
11703 };
11704 
11705 #ifdef __clang__
11706 #pragma clang diagnostic pop
11707 #elif defined(__GNUC__) || defined(__GNUG__)
11708 #pragma GCC diagnostic pop
11709 #endif
11710 
11711 NK_INTERN unsigned int
11712 nk_decompress_length(unsigned char *input)
11713 {
11714  return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
11715 }
11716 
11717 NK_GLOBAL unsigned char *nk__barrier;
11718 NK_GLOBAL unsigned char *nk__barrier2;
11719 NK_GLOBAL unsigned char *nk__barrier3;
11720 NK_GLOBAL unsigned char *nk__barrier4;
11721 NK_GLOBAL unsigned char *nk__dout;
11722 
11723 NK_INTERN void
11724 nk__match(unsigned char *data, unsigned int length)
11725 {
11726  /* INVERSE of memmove... write each byte before copying the next...*/
11727  NK_ASSERT (nk__dout + length <= nk__barrier);
11728  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
11729  if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
11730  while (length--) *nk__dout++ = *data++;
11731 }
11732 
11733 NK_INTERN void
11734 nk__lit(unsigned char *data, unsigned int length)
11735 {
11736  NK_ASSERT (nk__dout + length <= nk__barrier);
11737  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
11738  if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
11739  NK_MEMCPY(nk__dout, data, length);
11740  nk__dout += length;
11741 }
11742 
11743 #define nk__in2(x) ((i[x] << 8) + i[(x)+1])
11744 #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1))
11745 #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1))
11746 
11747 NK_INTERN unsigned char*
11748 nk_decompress_token(unsigned char *i)
11749 {
11750  if (*i >= 0x20) { /* use fewer if's for cases that expand small */
11751  if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
11752  else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
11753  else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
11754  } else { /* more ifs for cases that expand large, since overhead is amortized */
11755  if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
11756  else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
11757  else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
11758  else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
11759  else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
11760  else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
11761  }
11762  return i;
11763 }
11764 
11765 NK_INTERN unsigned int
11766 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
11767 {
11768  const unsigned long ADLER_MOD = 65521;
11769  unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
11770  unsigned long blocklen, i;
11771 
11772  blocklen = buflen % 5552;
11773  while (buflen) {
11774  for (i=0; i + 7 < blocklen; i += 8) {
11775  s1 += buffer[0]; s2 += s1;
11776  s1 += buffer[1]; s2 += s1;
11777  s1 += buffer[2]; s2 += s1;
11778  s1 += buffer[3]; s2 += s1;
11779  s1 += buffer[4]; s2 += s1;
11780  s1 += buffer[5]; s2 += s1;
11781  s1 += buffer[6]; s2 += s1;
11782  s1 += buffer[7]; s2 += s1;
11783  buffer += 8;
11784  }
11785  for (; i < blocklen; ++i) {
11786  s1 += *buffer++; s2 += s1;
11787  }
11788 
11789  s1 %= ADLER_MOD; s2 %= ADLER_MOD;
11790  buflen -= (unsigned int)blocklen;
11791  blocklen = 5552;
11792  }
11793  return (unsigned int)(s2 << 16) + (unsigned int)s1;
11794 }
11795 
11796 NK_INTERN unsigned int
11797 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
11798 {
11799  unsigned int olen;
11800  if (nk__in4(0) != 0x57bC0000) return 0;
11801  if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */
11802  olen = nk_decompress_length(i);
11803  nk__barrier2 = i;
11804  nk__barrier3 = i+length;
11805  nk__barrier = output + olen;
11806  nk__barrier4 = output;
11807  i += 16;
11808 
11809  nk__dout = output;
11810  for (;;) {
11811  unsigned char *old_i = i;
11812  i = nk_decompress_token(i);
11813  if (i == old_i) {
11814  if (*i == 0x05 && i[1] == 0xfa) {
11815  NK_ASSERT(nk__dout == output + olen);
11816  if (nk__dout != output + olen) return 0;
11817  if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
11818  return 0;
11819  return olen;
11820  } else {
11821  NK_ASSERT(0); /* NOTREACHED */
11822  return 0;
11823  }
11824  }
11825  NK_ASSERT(nk__dout <= output + olen);
11826  if (nk__dout > output + olen)
11827  return 0;
11828  }
11829 }
11830 
11831 NK_INTERN unsigned int
11832 nk_decode_85_byte(char c)
11833 { return (unsigned int)((c >= '\\') ? c-36 : c-35); }
11834 
11835 NK_INTERN void
11836 nk_decode_85(unsigned char* dst, const unsigned char* src)
11837 {
11838  while (*src)
11839  {
11840  unsigned int tmp =
11841  nk_decode_85_byte((char)src[0]) +
11842  85 * (nk_decode_85_byte((char)src[1]) +
11843  85 * (nk_decode_85_byte((char)src[2]) +
11844  85 * (nk_decode_85_byte((char)src[3]) +
11845  85 * nk_decode_85_byte((char)src[4]))));
11846 
11847  /* we can't assume little-endianess. */
11848  dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
11849  dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
11850  dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
11851  dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
11852 
11853  src += 5;
11854  dst += 4;
11855  }
11856 }
11857 
11858 /* -------------------------------------------------------------
11859  *
11860  * FONT ATLAS
11861  *
11862  * --------------------------------------------------------------*/
11863 NK_API struct nk_font_config
11864 nk_font_config(float pixel_height)
11865 {
11866  struct nk_font_config cfg;
11867  nk_zero_struct(cfg);
11868  cfg.ttf_blob = 0;
11869  cfg.ttf_size = 0;
11870  cfg.ttf_data_owned_by_atlas = 0;
11871  cfg.size = pixel_height;
11872  cfg.oversample_h = 3;
11873  cfg.oversample_v = 1;
11874  cfg.pixel_snap = 0;
11875  cfg.coord_type = NK_COORD_UV;
11876  cfg.spacing = nk_vec2(0,0);
11877  cfg.range = nk_font_default_glyph_ranges();
11878  cfg.merge_mode = 0;
11879  cfg.fallback_glyph = '?';
11880  cfg.font = 0;
11881  return cfg;
11882 }
11883 
11884 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
11885 NK_API void
11886 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
11887 {
11888  NK_ASSERT(atlas);
11889  if (!atlas) return;
11890  nk_zero_struct(*atlas);
11891  atlas->temporary.userdata.ptr = 0;
11892  atlas->temporary.alloc = nk_malloc;
11893  atlas->temporary.free = nk_mfree;
11894  atlas->permanent.userdata.ptr = 0;
11895  atlas->permanent.alloc = nk_malloc;
11896  atlas->permanent.free = nk_mfree;
11897 }
11898 #endif
11899 
11900 NK_API void
11901 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
11902 {
11903  NK_ASSERT(atlas);
11904  NK_ASSERT(alloc);
11905  if (!atlas || !alloc) return;
11906  nk_zero_struct(*atlas);
11907  atlas->permanent = *alloc;
11908  atlas->temporary = *alloc;
11909 }
11910 
11911 NK_API void
11912 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
11913  struct nk_allocator *permanent, struct nk_allocator *temporary)
11914 {
11915  NK_ASSERT(atlas);
11916  NK_ASSERT(permanent);
11917  NK_ASSERT(temporary);
11918  if (!atlas || !permanent || !temporary) return;
11919  nk_zero_struct(*atlas);
11920  atlas->permanent = *permanent;
11921  atlas->temporary = *temporary;
11922 }
11923 
11924 NK_API void
11925 nk_font_atlas_begin(struct nk_font_atlas *atlas)
11926 {
11927  NK_ASSERT(atlas);
11928  NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
11929  NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
11930  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
11931  !atlas->temporary.alloc || !atlas->temporary.free) return;
11932  if (atlas->glyphs) {
11933  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
11934  atlas->glyphs = 0;
11935  }
11936  if (atlas->pixel) {
11937  atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
11938  atlas->pixel = 0;
11939  }
11940 }
11941 
11942 NK_API struct nk_font*
11943 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
11944 {
11945  struct nk_font *font = 0;
11946  struct nk_font_config *cfg;
11947 
11948  NK_ASSERT(atlas);
11949  NK_ASSERT(atlas->permanent.alloc);
11950  NK_ASSERT(atlas->permanent.free);
11951  NK_ASSERT(atlas->temporary.alloc);
11952  NK_ASSERT(atlas->temporary.free);
11953 
11954  NK_ASSERT(config);
11955  NK_ASSERT(config->ttf_blob);
11956  NK_ASSERT(config->ttf_size);
11957  NK_ASSERT(config->size > 0.0f);
11958 
11959  if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
11960  !atlas->permanent.alloc || !atlas->permanent.free ||
11961  !atlas->temporary.alloc || !atlas->temporary.free)
11962  return 0;
11963 
11964  /* allocate and insert font config into list */
11965  cfg = (struct nk_font_config*)
11966  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
11967  NK_MEMCPY(cfg, config, sizeof(*config));
11968  if (!atlas->config) {
11969  atlas->config = cfg;
11970  cfg->next = 0;
11971  } else {
11972  cfg->next = atlas->config;
11973  atlas->config = cfg;
11974  }
11975 
11976  /* allocate new font */
11977  if (!config->merge_mode) {
11978  font = (struct nk_font*)
11979  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
11980  NK_ASSERT(font);
11981  if (!font) return 0;
11982  font->config = cfg;
11983  } else {
11984  NK_ASSERT(atlas->font_num);
11985  font = atlas->fonts;
11986  font->config = cfg;
11987  }
11988 
11989  /* insert font into list */
11990  if (!config->merge_mode) {
11991  if (!atlas->fonts) {
11992  atlas->fonts = font;
11993  font->next = 0;
11994  } else {
11995  font->next = atlas->fonts;
11996  atlas->fonts = font;
11997  }
11998  cfg->font = &font->info;
11999  }
12000 
12001  /* create own copy of .TTF font blob */
12002  if (!config->ttf_data_owned_by_atlas) {
12003  cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
12004  NK_ASSERT(cfg->ttf_blob);
12005  if (!cfg->ttf_blob) {
12006  atlas->font_num++;
12007  return 0;
12008  }
12009  NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
12010  cfg->ttf_data_owned_by_atlas = 1;
12011  }
12012  atlas->font_num++;
12013  return font;
12014 }
12015 
12016 NK_API struct nk_font*
12017 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
12018  nk_size size, float height, const struct nk_font_config *config)
12019 {
12020  struct nk_font_config cfg;
12021  NK_ASSERT(memory);
12022  NK_ASSERT(size);
12023 
12024  NK_ASSERT(atlas);
12025  NK_ASSERT(atlas->temporary.alloc);
12026  NK_ASSERT(atlas->temporary.free);
12027  NK_ASSERT(atlas->permanent.alloc);
12028  NK_ASSERT(atlas->permanent.free);
12029  if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
12030  !atlas->permanent.alloc || !atlas->permanent.free)
12031  return 0;
12032 
12033  cfg = (config) ? *config: nk_font_config(height);
12034  cfg.ttf_blob = memory;
12035  cfg.ttf_size = size;
12036  cfg.size = height;
12037  cfg.ttf_data_owned_by_atlas = 0;
12038  return nk_font_atlas_add(atlas, &cfg);
12039 }
12040 
12041 #ifdef NK_INCLUDE_STANDARD_IO
12042 NK_API struct nk_font*
12043 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
12044  float height, const struct nk_font_config *config)
12045 {
12046  nk_size size;
12047  char *memory;
12048  struct nk_font_config cfg;
12049 
12050  NK_ASSERT(atlas);
12051  NK_ASSERT(atlas->temporary.alloc);
12052  NK_ASSERT(atlas->temporary.free);
12053  NK_ASSERT(atlas->permanent.alloc);
12054  NK_ASSERT(atlas->permanent.free);
12055 
12056  if (!atlas || !file_path) return 0;
12057  memory = nk_file_load(file_path, &size, &atlas->permanent);
12058  if (!memory) return 0;
12059 
12060  cfg = (config) ? *config: nk_font_config(height);
12061  cfg.ttf_blob = memory;
12062  cfg.ttf_size = size;
12063  cfg.size = height;
12064  cfg.ttf_data_owned_by_atlas = 1;
12065  return nk_font_atlas_add(atlas, &cfg);
12066 }
12067 #endif
12068 
12069 NK_API struct nk_font*
12070 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
12071  void *compressed_data, nk_size compressed_size, float height,
12072  const struct nk_font_config *config)
12073 {
12074  unsigned int decompressed_size;
12075  void *decompressed_data;
12076  struct nk_font_config cfg;
12077 
12078  NK_ASSERT(atlas);
12079  NK_ASSERT(atlas->temporary.alloc);
12080  NK_ASSERT(atlas->temporary.free);
12081  NK_ASSERT(atlas->permanent.alloc);
12082  NK_ASSERT(atlas->permanent.free);
12083 
12084  NK_ASSERT(compressed_data);
12085  NK_ASSERT(compressed_size);
12086  if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
12087  !atlas->permanent.alloc || !atlas->permanent.free)
12088  return 0;
12089 
12090  decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
12091  decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
12092  NK_ASSERT(decompressed_data);
12093  if (!decompressed_data) return 0;
12094  nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
12095  (unsigned int)compressed_size);
12096 
12097  cfg = (config) ? *config: nk_font_config(height);
12098  cfg.ttf_blob = decompressed_data;
12099  cfg.ttf_size = decompressed_size;
12100  cfg.size = height;
12101  cfg.ttf_data_owned_by_atlas = 1;
12102  return nk_font_atlas_add(atlas, &cfg);
12103 }
12104 
12105 NK_API struct nk_font*
12106 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
12107  const char *data_base85, float height, const struct nk_font_config *config)
12108 {
12109  int compressed_size;
12110  void *compressed_data;
12111  struct nk_font *font;
12112 
12113  NK_ASSERT(atlas);
12114  NK_ASSERT(atlas->temporary.alloc);
12115  NK_ASSERT(atlas->temporary.free);
12116  NK_ASSERT(atlas->permanent.alloc);
12117  NK_ASSERT(atlas->permanent.free);
12118 
12119  NK_ASSERT(data_base85);
12120  if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
12121  !atlas->permanent.alloc || !atlas->permanent.free)
12122  return 0;
12123 
12124  compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
12125  compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
12126  NK_ASSERT(compressed_data);
12127  if (!compressed_data) return 0;
12128  nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
12129  font = nk_font_atlas_add_compressed(atlas, compressed_data,
12130  (nk_size)compressed_size, height, config);
12131  atlas->temporary.free(atlas->temporary.userdata, compressed_data);
12132  return font;
12133 }
12134 
12135 #ifdef NK_INCLUDE_DEFAULT_FONT
12136 NK_API struct nk_font*
12137 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
12138  float pixel_height, const struct nk_font_config *config)
12139 {
12140  NK_ASSERT(atlas);
12141  NK_ASSERT(atlas->temporary.alloc);
12142  NK_ASSERT(atlas->temporary.free);
12143  NK_ASSERT(atlas->permanent.alloc);
12144  NK_ASSERT(atlas->permanent.free);
12145  return nk_font_atlas_add_compressed_base85(atlas,
12146  nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
12147 }
12148 #endif
12149 
12150 NK_API const void*
12151 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
12152  enum nk_font_atlas_format fmt)
12153 {
12154  int i = 0;
12155  void *tmp = 0;
12156  nk_size tmp_size, img_size;
12157  struct nk_font *font_iter;
12158  struct nk_font_baker *baker;
12159 
12160  NK_ASSERT(atlas);
12161  NK_ASSERT(atlas->temporary.alloc);
12162  NK_ASSERT(atlas->temporary.free);
12163  NK_ASSERT(atlas->permanent.alloc);
12164  NK_ASSERT(atlas->permanent.free);
12165 
12166  NK_ASSERT(width);
12167  NK_ASSERT(height);
12168  if (!atlas || !width || !height ||
12169  !atlas->temporary.alloc || !atlas->temporary.free ||
12170  !atlas->permanent.alloc || !atlas->permanent.free)
12171  return 0;
12172 
12173 #ifdef NK_INCLUDE_DEFAULT_FONT
12174  /* no font added so just use default font */
12175  if (!atlas->font_num)
12176  atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
12177 #endif
12178  NK_ASSERT(atlas->font_num);
12179  if (!atlas->font_num) return 0;
12180 
12181  /* allocate temporary baker memory required for the baking process */
12182  nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
12183  tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
12184  NK_ASSERT(tmp);
12185  if (!tmp) goto failed;
12186 
12187  /* allocate glyph memory for all fonts */
12188  baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
12189  atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
12190  atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
12191  NK_ASSERT(atlas->glyphs);
12192  if (!atlas->glyphs)
12193  goto failed;
12194 
12195  /* pack all glyphs into a tight fit space */
12196  atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
12197  atlas->custom.h = NK_CURSOR_DATA_H + 1;
12198  if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
12199  atlas->config, atlas->font_num, &atlas->temporary))
12200  goto failed;
12201 
12202  /* allocate memory for the baked image font atlas */
12203  atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
12204  NK_ASSERT(atlas->pixel);
12205  if (!atlas->pixel)
12206  goto failed;
12207 
12208  /* bake glyphs and custom white pixel into image */
12209  nk_font_bake(baker, atlas->pixel, *width, *height,
12210  atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
12211  nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
12212  nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
12213 
12214  if (fmt == NK_FONT_ATLAS_RGBA32) {
12215  /* convert alpha8 image into rgba32 image */
12216  void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
12217  (nk_size)(*width * *height * 4));
12218  NK_ASSERT(img_rgba);
12219  if (!img_rgba) goto failed;
12220  nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
12221  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12222  atlas->pixel = img_rgba;
12223  }
12224  atlas->tex_width = *width;
12225  atlas->tex_height = *height;
12226 
12227  /* initialize each font */
12228  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
12229  struct nk_font *font = font_iter;
12230  struct nk_font_config *config = font->config;
12231  nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
12232  config->font, nk_handle_ptr(0));
12233  }
12234 
12235  /* initialize each cursor */
12236  {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
12237  /* Pos ----- Size ------- Offset --*/
12238  {{ 0, 3}, {12,19}, { 0, 0}},
12239  {{13, 0}, { 7,16}, { 4, 8}},
12240  {{31, 0}, {23,23}, {11,11}},
12241  {{21, 0}, { 9, 23}, { 5,11}},
12242  {{55,18}, {23, 9}, {11, 5}},
12243  {{73, 0}, {17,17}, { 9, 9}},
12244  {{55, 0}, {17,17}, { 9, 9}}
12245  };
12246  for (i = 0; i < NK_CURSOR_COUNT; ++i) {
12247  struct nk_cursor *cursor = &atlas->cursors[i];
12248  cursor->img.w = (unsigned short)*width;
12249  cursor->img.h = (unsigned short)*height;
12250  cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
12251  cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
12252  cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
12253  cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
12254  cursor->size = nk_cursor_data[i][1];
12255  cursor->offset = nk_cursor_data[i][2];
12256  }}
12257  /* free temporary memory */
12258  atlas->temporary.free(atlas->temporary.userdata, tmp);
12259  return atlas->pixel;
12260 
12261 failed:
12262  /* error so cleanup all memory */
12263  if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
12264  if (atlas->glyphs) {
12265  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12266  atlas->glyphs = 0;
12267  }
12268  if (atlas->pixel) {
12269  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12270  atlas->pixel = 0;
12271  }
12272  return 0;
12273 }
12274 
12275 NK_API void
12276 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
12277  struct nk_draw_null_texture *null)
12278 {
12279  int i = 0;
12280  struct nk_font *font_iter;
12281  NK_ASSERT(atlas);
12282  if (!atlas) {
12283  if (!null) return;
12284  null->texture = texture;
12285  null->uv = nk_vec2(0.5f,0.5f);
12286  }
12287  if (null) {
12288  null->texture = texture;
12289  null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
12290  null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
12291  }
12292  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
12293  font_iter->texture = texture;
12294 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
12295  font_iter->handle.texture = texture;
12296 #endif
12297  }
12298  for (i = 0; i < NK_CURSOR_COUNT; ++i)
12299  atlas->cursors[i].img.handle = texture;
12300 
12301  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12302  atlas->pixel = 0;
12303  atlas->tex_width = 0;
12304  atlas->tex_height = 0;
12305  atlas->custom.x = 0;
12306  atlas->custom.y = 0;
12307  atlas->custom.w = 0;
12308  atlas->custom.h = 0;
12309 }
12310 
12311 NK_API void
12312 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
12313 {
12314  NK_ASSERT(atlas);
12315  NK_ASSERT(atlas->temporary.alloc);
12316  NK_ASSERT(atlas->temporary.free);
12317  NK_ASSERT(atlas->permanent.alloc);
12318  NK_ASSERT(atlas->permanent.free);
12319 
12320  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
12321  if (atlas->config) {
12322  struct nk_font_config *iter, *next;
12323  for (iter = atlas->config; iter; iter = next) {
12324  next = iter->next;
12325  atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
12326  atlas->permanent.free(atlas->permanent.userdata, iter);
12327  }
12328  }
12329 }
12330 
12331 NK_API void
12332 nk_font_atlas_clear(struct nk_font_atlas *atlas)
12333 {
12334  NK_ASSERT(atlas);
12335  NK_ASSERT(atlas->temporary.alloc);
12336  NK_ASSERT(atlas->temporary.free);
12337  NK_ASSERT(atlas->permanent.alloc);
12338  NK_ASSERT(atlas->permanent.free);
12339  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
12340 
12341  nk_font_atlas_cleanup(atlas);
12342  if (atlas->fonts) {
12343  struct nk_font *iter, *next;
12344  for (iter = atlas->fonts; iter; iter = next) {
12345  next = iter->next;
12346  atlas->permanent.free(atlas->permanent.userdata, iter);
12347  }
12348  atlas->fonts = 0;
12349  }
12350  if (atlas->glyphs)
12351  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12352  nk_zero_struct(*atlas);
12353 }
12354 #endif
12355 /* ==============================================================
12356  *
12357  * INPUT
12358  *
12359  * ===============================================================*/
12360 NK_API void
12361 nk_input_begin(struct nk_context *ctx)
12362 {
12363  int i;
12364  struct nk_input *in;
12365  NK_ASSERT(ctx);
12366  if (!ctx) return;
12367  in = &ctx->input;
12368  for (i = 0; i < NK_BUTTON_MAX; ++i)
12369  in->mouse.buttons[i].clicked = 0;
12370 
12371  in->keyboard.text_len = 0;
12372  in->mouse.scroll_delta = nk_vec2(0,0);
12373  in->mouse.prev.x = in->mouse.pos.x;
12374  in->mouse.prev.y = in->mouse.pos.y;
12375  in->mouse.delta.x = 0;
12376  in->mouse.delta.y = 0;
12377  for (i = 0; i < NK_KEY_MAX; i++)
12378  in->keyboard.keys[i].clicked = 0;
12379 }
12380 
12381 NK_API void
12382 nk_input_end(struct nk_context *ctx)
12383 {
12384  struct nk_input *in;
12385  NK_ASSERT(ctx);
12386  if (!ctx) return;
12387  in = &ctx->input;
12388  if (in->mouse.grab)
12389  in->mouse.grab = 0;
12390  if (in->mouse.ungrab) {
12391  in->mouse.grabbed = 0;
12392  in->mouse.ungrab = 0;
12393  in->mouse.grab = 0;
12394  }
12395 }
12396 
12397 NK_API void
12398 nk_input_motion(struct nk_context *ctx, int x, int y)
12399 {
12400  struct nk_input *in;
12401  NK_ASSERT(ctx);
12402  if (!ctx) return;
12403  in = &ctx->input;
12404  in->mouse.pos.x = (float)x;
12405  in->mouse.pos.y = (float)y;
12406  in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
12407  in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
12408 }
12409 
12410 NK_API void
12411 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down)
12412 {
12413  struct nk_input *in;
12414  NK_ASSERT(ctx);
12415  if (!ctx) return;
12416  in = &ctx->input;
12417  if (in->keyboard.keys[key].down != down)
12418  in->keyboard.keys[key].clicked++;
12419  in->keyboard.keys[key].down = down;
12420 }
12421 
12422 NK_API void
12423 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down)
12424 {
12425  struct nk_mouse_button *btn;
12426  struct nk_input *in;
12427  NK_ASSERT(ctx);
12428  if (!ctx) return;
12429  in = &ctx->input;
12430  if (in->mouse.buttons[id].down == down) return;
12431 
12432  btn = &in->mouse.buttons[id];
12433  btn->clicked_pos.x = (float)x;
12434  btn->clicked_pos.y = (float)y;
12435  btn->down = down;
12436  btn->clicked++;
12437 }
12438 
12439 NK_API void
12440 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
12441 {
12442  NK_ASSERT(ctx);
12443  if (!ctx) return;
12444  ctx->input.mouse.scroll_delta.x += val.x;
12445  ctx->input.mouse.scroll_delta.y += val.y;
12446 }
12447 
12448 NK_API void
12449 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
12450 {
12451  int len = 0;
12452  nk_rune unicode;
12453  struct nk_input *in;
12454 
12455  NK_ASSERT(ctx);
12456  if (!ctx) return;
12457  in = &ctx->input;
12458 
12459  len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
12460  if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
12461  nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
12463  in->keyboard.text_len += len;
12464  }
12465 }
12466 
12467 NK_API void
12468 nk_input_char(struct nk_context *ctx, char c)
12469 {
12470  nk_glyph glyph;
12471  NK_ASSERT(ctx);
12472  if (!ctx) return;
12473  glyph[0] = c;
12474  nk_input_glyph(ctx, glyph);
12475 }
12476 
12477 NK_API void
12478 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
12479 {
12480  nk_glyph rune;
12481  NK_ASSERT(ctx);
12482  if (!ctx) return;
12483  nk_utf_encode(unicode, rune, NK_UTF_SIZE);
12484  nk_input_glyph(ctx, rune);
12485 }
12486 
12487 NK_API int
12488 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
12489 {
12490  const struct nk_mouse_button *btn;
12491  if (!i) return nk_false;
12492  btn = &i->mouse.buttons[id];
12493  return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
12494 }
12495 
12496 NK_API int
12497 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
12498  struct nk_rect b)
12499 {
12500  const struct nk_mouse_button *btn;
12501  if (!i) return nk_false;
12502  btn = &i->mouse.buttons[id];
12503  if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
12504  return nk_false;
12505  return nk_true;
12506 }
12507 
12508 NK_API int
12510  struct nk_rect b, int down)
12511 {
12512  const struct nk_mouse_button *btn;
12513  if (!i) return nk_false;
12514  btn = &i->mouse.buttons[id];
12515  return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
12516 }
12517 
12518 NK_API int
12519 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
12520  struct nk_rect b)
12521 {
12522  const struct nk_mouse_button *btn;
12523  if (!i) return nk_false;
12524  btn = &i->mouse.buttons[id];
12525  return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) &&
12526  btn->clicked) ? nk_true : nk_false;
12527 }
12528 
12529 NK_API int
12531  struct nk_rect b, int down)
12532 {
12533  const struct nk_mouse_button *btn;
12534  if (!i) return nk_false;
12535  btn = &i->mouse.buttons[id];
12536  return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
12537  btn->clicked) ? nk_true : nk_false;
12538 }
12539 
12540 NK_API int
12541 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
12542 {
12543  int i, down = 0;
12544  for (i = 0; i < NK_BUTTON_MAX; ++i)
12545  down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b);
12546  return down;
12547 }
12548 
12549 NK_API int
12550 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
12551 {
12552  if (!i) return nk_false;
12553  return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
12554 }
12555 
12556 NK_API int
12557 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
12558 {
12559  if (!i) return nk_false;
12560  return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
12561 }
12562 
12563 NK_API int
12564 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
12565 {
12566  if (!i) return nk_false;
12567  if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
12568  return nk_input_is_mouse_click_in_rect(i, id, rect);
12569 }
12570 
12571 NK_API int
12572 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
12573 {
12574  if (!i) return nk_false;
12575  return i->mouse.buttons[id].down;
12576 }
12577 
12578 NK_API int
12579 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
12580 {
12581  const struct nk_mouse_button *b;
12582  if (!i) return nk_false;
12583  b = &i->mouse.buttons[id];
12584  if (b->down && b->clicked)
12585  return nk_true;
12586  return nk_false;
12587 }
12588 
12589 NK_API int
12590 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
12591 {
12592  if (!i) return nk_false;
12593  return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
12594 }
12595 
12596 NK_API int
12597 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
12598 {
12599  const struct nk_key *k;
12600  if (!i) return nk_false;
12601  k = &i->keyboard.keys[key];
12602  if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
12603  return nk_true;
12604  return nk_false;
12605 }
12606 
12607 NK_API int
12608 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
12609 {
12610  const struct nk_key *k;
12611  if (!i) return nk_false;
12612  k = &i->keyboard.keys[key];
12613  if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
12614  return nk_true;
12615  return nk_false;
12616 }
12617 
12618 NK_API int
12619 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
12620 {
12621  const struct nk_key *k;
12622  if (!i) return nk_false;
12623  k = &i->keyboard.keys[key];
12624  if (k->down) return nk_true;
12625  return nk_false;
12626 }
12627 
12628 /*
12629  * ==============================================================
12630  *
12631  * TEXT EDITOR
12632  *
12633  * ===============================================================
12634  */
12635 /* stb_textedit.h - v1.8 - public domain - Sean Barrett */
12636 struct nk_text_find {
12637  float x,y; /* position of n'th character */
12638  float height; /* height of line */
12639  int first_char, length; /* first char of row, and length */
12640  int prev_first; /*_ first char of previous row */
12641 };
12642 
12643 struct nk_text_edit_row {
12644  float x0,x1;
12645  /* starting x location, end x location (allows for align=right, etc) */
12646  float baseline_y_delta;
12647  /* position of baseline relative to previous row's baseline*/
12648  float ymin,ymax;
12649  /* height of row above and below baseline */
12650  int num_chars;
12651 };
12652 
12653 /* forward declarations */
12654 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
12655 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
12656 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
12657 #define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
12658 
12659 NK_INTERN float
12660 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
12661  const struct nk_user_font *font)
12662 {
12663  int len = 0;
12664  nk_rune unicode = 0;
12665  const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
12666  return font->width(font->userdata, font->height, str, len);
12667 }
12668 
12669 NK_INTERN void
12670 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
12671  int line_start_id, float row_height, const struct nk_user_font *font)
12672 {
12673  int l;
12674  int glyphs = 0;
12675  nk_rune unicode;
12676  const char *remaining;
12677  int len = nk_str_len_char(&edit->string);
12678  const char *end = nk_str_get_const(&edit->string) + len;
12679  const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
12680  const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
12681  text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
12682 
12683  r->x0 = 0.0f;
12684  r->x1 = size.x;
12685  r->baseline_y_delta = size.y;
12686  r->ymin = 0.0f;
12687  r->ymax = size.y;
12688  r->num_chars = glyphs;
12689 }
12690 
12691 NK_INTERN int
12692 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
12693  const struct nk_user_font *font, float row_height)
12694 {
12695  struct nk_text_edit_row r;
12696  int n = edit->string.len;
12697  float base_y = 0, prev_x;
12698  int i=0, k;
12699 
12700  r.x0 = r.x1 = 0;
12701  r.ymin = r.ymax = 0;
12702  r.num_chars = 0;
12703 
12704  /* search rows to find one that straddles 'y' */
12705  while (i < n) {
12706  nk_textedit_layout_row(&r, edit, i, row_height, font);
12707  if (r.num_chars <= 0)
12708  return n;
12709 
12710  if (i==0 && y < base_y + r.ymin)
12711  return 0;
12712 
12713  if (y < base_y + r.ymax)
12714  break;
12715 
12716  i += r.num_chars;
12717  base_y += r.baseline_y_delta;
12718  }
12719 
12720  /* below all text, return 'after' last character */
12721  if (i >= n)
12722  return n;
12723 
12724  /* check if it's before the beginning of the line */
12725  if (x < r.x0)
12726  return i;
12727 
12728  /* check if it's before the end of the line */
12729  if (x < r.x1) {
12730  /* search characters in row for one that straddles 'x' */
12731  k = i;
12732  prev_x = r.x0;
12733  for (i=0; i < r.num_chars; ++i) {
12734  float w = nk_textedit_get_width(edit, k, i, font);
12735  if (x < prev_x+w) {
12736  if (x < prev_x+w/2)
12737  return k+i;
12738  else return k+i+1;
12739  }
12740  prev_x += w;
12741  }
12742  /* shouldn't happen, but if it does, fall through to end-of-line case */
12743  }
12744 
12745  /* if the last character is a newline, return that.
12746  * otherwise return 'after' the last character */
12747  if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
12748  return i+r.num_chars-1;
12749  else return i+r.num_chars;
12750 }
12751 
12752 NK_INTERN void
12753 nk_textedit_click(struct nk_text_edit *state, float x, float y,
12754  const struct nk_user_font *font, float row_height)
12755 {
12756  /* API click: on mouse down, move the cursor to the clicked location,
12757  * and reset the selection */
12758  state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
12759  state->select_start = state->cursor;
12760  state->select_end = state->cursor;
12761  state->has_preferred_x = 0;
12762 }
12763 
12764 NK_INTERN void
12765 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
12766  const struct nk_user_font *font, float row_height)
12767 {
12768  /* API drag: on mouse drag, move the cursor and selection endpoint
12769  * to the clicked location */
12770  int p = nk_textedit_locate_coord(state, x, y, font, row_height);
12771  if (state->select_start == state->select_end)
12772  state->select_start = state->cursor;
12773  state->cursor = state->select_end = p;
12774 }
12775 
12776 NK_INTERN void
12777 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
12778  int n, int single_line, const struct nk_user_font *font, float row_height)
12779 {
12780  /* find the x/y location of a character, and remember info about the previous
12781  * row in case we get a move-up event (for page up, we'll have to rescan) */
12782  struct nk_text_edit_row r;
12783  int prev_start = 0;
12784  int z = state->string.len;
12785  int i=0, first;
12786 
12787  nk_zero_struct(r);
12788  if (n == z) {
12789  /* if it's at the end, then find the last line -- simpler than trying to
12790  explicitly handle this case in the regular code */
12791  nk_textedit_layout_row(&r, state, 0, row_height, font);
12792  if (single_line) {
12793  find->first_char = 0;
12794  find->length = z;
12795  } else {
12796  while (i < z) {
12797  prev_start = i;
12798  i += r.num_chars;
12799  nk_textedit_layout_row(&r, state, i, row_height, font);
12800  }
12801 
12802  find->first_char = i;
12803  find->length = r.num_chars;
12804  }
12805  find->x = r.x1;
12806  find->y = r.ymin;
12807  find->height = r.ymax - r.ymin;
12808  find->prev_first = prev_start;
12809  return;
12810  }
12811 
12812  /* search rows to find the one that straddles character n */
12813  find->y = 0;
12814 
12815  for(;;) {
12816  nk_textedit_layout_row(&r, state, i, row_height, font);
12817  if (n < i + r.num_chars) break;
12818  prev_start = i;
12819  i += r.num_chars;
12820  find->y += r.baseline_y_delta;
12821  }
12822 
12823  find->first_char = first = i;
12824  find->length = r.num_chars;
12825  find->height = r.ymax - r.ymin;
12826  find->prev_first = prev_start;
12827 
12828  /* now scan to find xpos */
12829  find->x = r.x0;
12830  for (i=0; first+i < n; ++i)
12831  find->x += nk_textedit_get_width(state, first, i, font);
12832 }
12833 
12834 NK_INTERN void
12835 nk_textedit_clamp(struct nk_text_edit *state)
12836 {
12837  /* make the selection/cursor state valid if client altered the string */
12838  int n = state->string.len;
12839  if (NK_TEXT_HAS_SELECTION(state)) {
12840  if (state->select_start > n) state->select_start = n;
12841  if (state->select_end > n) state->select_end = n;
12842  /* if clamping forced them to be equal, move the cursor to match */
12843  if (state->select_start == state->select_end)
12844  state->cursor = state->select_start;
12845  }
12846  if (state->cursor > n) state->cursor = n;
12847 }
12848 
12849 NK_API void
12850 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
12851 {
12852  /* delete characters while updating undo */
12853  nk_textedit_makeundo_delete(state, where, len);
12854  nk_str_delete_runes(&state->string, where, len);
12855  state->has_preferred_x = 0;
12856 }
12857 
12858 NK_API void
12860 {
12861  /* delete the section */
12862  nk_textedit_clamp(state);
12863  if (NK_TEXT_HAS_SELECTION(state)) {
12864  if (state->select_start < state->select_end) {
12865  nk_textedit_delete(state, state->select_start,
12866  state->select_end - state->select_start);
12867  state->select_end = state->cursor = state->select_start;
12868  } else {
12869  nk_textedit_delete(state, state->select_end,
12870  state->select_start - state->select_end);
12871  state->select_start = state->cursor = state->select_end;
12872  }
12873  state->has_preferred_x = 0;
12874  }
12875 }
12876 
12877 NK_INTERN void
12878 nk_textedit_sortselection(struct nk_text_edit *state)
12879 {
12880  /* canonicalize the selection so start <= end */
12881  if (state->select_end < state->select_start) {
12882  int temp = state->select_end;
12883  state->select_end = state->select_start;
12884  state->select_start = temp;
12885  }
12886 }
12887 
12888 NK_INTERN void
12889 nk_textedit_move_to_first(struct nk_text_edit *state)
12890 {
12891  /* move cursor to first character of selection */
12892  if (NK_TEXT_HAS_SELECTION(state)) {
12893  nk_textedit_sortselection(state);
12894  state->cursor = state->select_start;
12895  state->select_end = state->select_start;
12896  state->has_preferred_x = 0;
12897  }
12898 }
12899 
12900 NK_INTERN void
12901 nk_textedit_move_to_last(struct nk_text_edit *state)
12902 {
12903  /* move cursor to last character of selection */
12904  if (NK_TEXT_HAS_SELECTION(state)) {
12905  nk_textedit_sortselection(state);
12906  nk_textedit_clamp(state);
12907  state->cursor = state->select_end;
12908  state->select_start = state->select_end;
12909  state->has_preferred_x = 0;
12910  }
12911 }
12912 
12913 NK_INTERN int
12914 nk_is_word_boundary( struct nk_text_edit *state, int idx)
12915 {
12916  int len;
12917  nk_rune c;
12918  if (idx <= 0) return 1;
12919  if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
12920  return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
12921  c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
12922  c == '|');
12923 }
12924 
12925 NK_INTERN int
12926 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
12927 {
12928  int c = state->cursor - 1;
12929  while( c >= 0 && !nk_is_word_boundary(state, c))
12930  --c;
12931 
12932  if( c < 0 )
12933  c = 0;
12934 
12935  return c;
12936 }
12937 
12938 NK_INTERN int
12939 nk_textedit_move_to_word_next(struct nk_text_edit *state)
12940 {
12941  const int len = state->string.len;
12942  int c = state->cursor+1;
12943  while( c < len && !nk_is_word_boundary(state, c))
12944  ++c;
12945 
12946  if( c > len )
12947  c = len;
12948 
12949  return c;
12950 }
12951 
12952 NK_INTERN void
12953 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
12954 {
12955  /* update selection and cursor to match each other */
12956  if (!NK_TEXT_HAS_SELECTION(state))
12957  state->select_start = state->select_end = state->cursor;
12958  else state->cursor = state->select_end;
12959 }
12960 
12961 NK_API int
12962 nk_textedit_cut(struct nk_text_edit *state)
12963 {
12964  /* API cut: delete selection */
12965  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
12966  return 0;
12967  if (NK_TEXT_HAS_SELECTION(state)) {
12968  nk_textedit_delete_selection(state); /* implicitly clamps */
12969  state->has_preferred_x = 0;
12970  return 1;
12971  }
12972  return 0;
12973 }
12974 
12975 NK_API int
12976 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
12977 {
12978  /* API paste: replace existing selection with passed-in text */
12979  int glyphs;
12980  const char *text = (const char *) ctext;
12981  if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
12982 
12983  /* if there's a selection, the paste should delete it */
12984  nk_textedit_clamp(state);
12986 
12987  /* try to insert the characters */
12988  glyphs = nk_utf_len(ctext, len);
12989  if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
12990  nk_textedit_makeundo_insert(state, state->cursor, glyphs);
12991  state->cursor += len;
12992  state->has_preferred_x = 0;
12993  return 1;
12994  }
12995  /* remove the undo since we didn't actually insert the characters */
12996  if (state->undo.undo_point)
12997  --state->undo.undo_point;
12998  return 0;
12999 }
13000 
13001 NK_API void
13002 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
13003 {
13004  nk_rune unicode;
13005  int glyph_len;
13006  int text_len = 0;
13007 
13008  NK_ASSERT(state);
13009  NK_ASSERT(text);
13010  if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
13011 
13012  glyph_len = nk_utf_decode(text, &unicode, total_len);
13013  while ((text_len < total_len) && glyph_len)
13014  {
13015  /* don't insert a backward delete, just process the event */
13016  if (unicode == 127) goto next;
13017  /* can't add newline in single-line mode */
13018  if (unicode == '\n' && state->single_line) goto next;
13019  /* filter incoming text */
13020  if (state->filter && !state->filter(state, unicode)) goto next;
13021 
13022  if (!NK_TEXT_HAS_SELECTION(state) &&
13023  state->cursor < state->string.len)
13024  {
13025  if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
13026  nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
13027  nk_str_delete_runes(&state->string, state->cursor, 1);
13028  }
13029  if (nk_str_insert_text_utf8(&state->string, state->cursor,
13030  text+text_len, 1))
13031  {
13032  ++state->cursor;
13033  state->has_preferred_x = 0;
13034  }
13035  } else {
13036  nk_textedit_delete_selection(state); /* implicitly clamps */
13037  if (nk_str_insert_text_utf8(&state->string, state->cursor,
13038  text+text_len, 1))
13039  {
13040  nk_textedit_makeundo_insert(state, state->cursor, 1);
13041  ++state->cursor;
13042  state->has_preferred_x = 0;
13043  }
13044  }
13045  next:
13046  text_len += glyph_len;
13047  glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
13048  }
13049 }
13050 
13051 NK_INTERN void
13052 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
13053  const struct nk_user_font *font, float row_height)
13054 {
13055 retry:
13056  switch (key)
13057  {
13058  case NK_KEY_NONE:
13059  case NK_KEY_CTRL:
13060  case NK_KEY_ENTER:
13061  case NK_KEY_SHIFT:
13062  case NK_KEY_TAB:
13063  case NK_KEY_COPY:
13064  case NK_KEY_CUT:
13065  case NK_KEY_PASTE:
13066  case NK_KEY_MAX:
13067  default: break;
13068  case NK_KEY_TEXT_UNDO:
13069  nk_textedit_undo(state);
13070  state->has_preferred_x = 0;
13071  break;
13072 
13073  case NK_KEY_TEXT_REDO:
13074  nk_textedit_redo(state);
13075  state->has_preferred_x = 0;
13076  break;
13077 
13079  nk_textedit_select_all(state);
13080  state->has_preferred_x = 0;
13081  break;
13082 
13084  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13085  state->mode = NK_TEXT_EDIT_MODE_INSERT;
13086  break;
13088  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13090  break;
13092  if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
13093  state->mode == NK_TEXT_EDIT_MODE_REPLACE)
13094  state->mode = NK_TEXT_EDIT_MODE_VIEW;
13095  break;
13096 
13097  case NK_KEY_LEFT:
13098  if (shift_mod) {
13099  nk_textedit_clamp(state);
13100  nk_textedit_prep_selection_at_cursor(state);
13101  /* move selection left */
13102  if (state->select_end > 0)
13103  --state->select_end;
13104  state->cursor = state->select_end;
13105  state->has_preferred_x = 0;
13106  } else {
13107  /* if currently there's a selection,
13108  * move cursor to start of selection */
13109  if (NK_TEXT_HAS_SELECTION(state))
13110  nk_textedit_move_to_first(state);
13111  else if (state->cursor > 0)
13112  --state->cursor;
13113  state->has_preferred_x = 0;
13114  } break;
13115 
13116  case NK_KEY_RIGHT:
13117  if (shift_mod) {
13118  nk_textedit_prep_selection_at_cursor(state);
13119  /* move selection right */
13120  ++state->select_end;
13121  nk_textedit_clamp(state);
13122  state->cursor = state->select_end;
13123  state->has_preferred_x = 0;
13124  } else {
13125  /* if currently there's a selection,
13126  * move cursor to end of selection */
13127  if (NK_TEXT_HAS_SELECTION(state))
13128  nk_textedit_move_to_last(state);
13129  else ++state->cursor;
13130  nk_textedit_clamp(state);
13131  state->has_preferred_x = 0;
13132  } break;
13133 
13134  case NK_KEY_TEXT_WORD_LEFT:
13135  if (shift_mod) {
13136  if( !NK_TEXT_HAS_SELECTION( state ) )
13137  nk_textedit_prep_selection_at_cursor(state);
13138  state->cursor = nk_textedit_move_to_word_previous(state);
13139  state->select_end = state->cursor;
13140  nk_textedit_clamp(state );
13141  } else {
13142  if (NK_TEXT_HAS_SELECTION(state))
13143  nk_textedit_move_to_first(state);
13144  else {
13145  state->cursor = nk_textedit_move_to_word_previous(state);
13146  nk_textedit_clamp(state );
13147  }
13148  } break;
13149 
13151  if (shift_mod) {
13152  if( !NK_TEXT_HAS_SELECTION( state ) )
13153  nk_textedit_prep_selection_at_cursor(state);
13154  state->cursor = nk_textedit_move_to_word_next(state);
13155  state->select_end = state->cursor;
13156  nk_textedit_clamp(state);
13157  } else {
13158  if (NK_TEXT_HAS_SELECTION(state))
13159  nk_textedit_move_to_last(state);
13160  else {
13161  state->cursor = nk_textedit_move_to_word_next(state);
13162  nk_textedit_clamp(state );
13163  }
13164  } break;
13165 
13166  case NK_KEY_DOWN: {
13167  struct nk_text_find find;
13168  struct nk_text_edit_row row;
13169  int i, sel = shift_mod;
13170 
13171  if (state->single_line) {
13172  /* on windows, up&down in single-line behave like left&right */
13173  key = NK_KEY_RIGHT;
13174  goto retry;
13175  }
13176 
13177  if (sel)
13178  nk_textedit_prep_selection_at_cursor(state);
13179  else if (NK_TEXT_HAS_SELECTION(state))
13180  nk_textedit_move_to_last(state);
13181 
13182  /* compute current position of cursor point */
13183  nk_textedit_clamp(state);
13184  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13185  font, row_height);
13186 
13187  /* now find character position down a row */
13188  if (find.length)
13189  {
13190  float x;
13191  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
13192  int start = find.first_char + find.length;
13193 
13194  state->cursor = start;
13195  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
13196  x = row.x0;
13197 
13198  for (i=0; i < row.num_chars && x < row.x1; ++i) {
13199  float dx = nk_textedit_get_width(state, start, i, font);
13200  x += dx;
13201  if (x > goal_x)
13202  break;
13203  ++state->cursor;
13204  }
13205  nk_textedit_clamp(state);
13206 
13207  state->has_preferred_x = 1;
13208  state->preferred_x = goal_x;
13209  if (sel)
13210  state->select_end = state->cursor;
13211  }
13212  } break;
13213 
13214  case NK_KEY_UP: {
13215  struct nk_text_find find;
13216  struct nk_text_edit_row row;
13217  int i, sel = shift_mod;
13218 
13219  if (state->single_line) {
13220  /* on windows, up&down become left&right */
13221  key = NK_KEY_LEFT;
13222  goto retry;
13223  }
13224 
13225  if (sel)
13226  nk_textedit_prep_selection_at_cursor(state);
13227  else if (NK_TEXT_HAS_SELECTION(state))
13228  nk_textedit_move_to_first(state);
13229 
13230  /* compute current position of cursor point */
13231  nk_textedit_clamp(state);
13232  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13233  font, row_height);
13234 
13235  /* can only go up if there's a previous row */
13236  if (find.prev_first != find.first_char) {
13237  /* now find character position up a row */
13238  float x;
13239  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
13240 
13241  state->cursor = find.prev_first;
13242  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
13243  x = row.x0;
13244 
13245  for (i=0; i < row.num_chars && x < row.x1; ++i) {
13246  float dx = nk_textedit_get_width(state, find.prev_first, i, font);
13247  x += dx;
13248  if (x > goal_x)
13249  break;
13250  ++state->cursor;
13251  }
13252  nk_textedit_clamp(state);
13253 
13254  state->has_preferred_x = 1;
13255  state->preferred_x = goal_x;
13256  if (sel) state->select_end = state->cursor;
13257  }
13258  } break;
13259 
13260  case NK_KEY_DEL:
13261  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13262  break;
13263  if (NK_TEXT_HAS_SELECTION(state))
13265  else {
13266  int n = state->string.len;
13267  if (state->cursor < n)
13268  nk_textedit_delete(state, state->cursor, 1);
13269  }
13270  state->has_preferred_x = 0;
13271  break;
13272 
13273  case NK_KEY_BACKSPACE:
13274  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13275  break;
13276  if (NK_TEXT_HAS_SELECTION(state))
13278  else {
13279  nk_textedit_clamp(state);
13280  if (state->cursor > 0) {
13281  nk_textedit_delete(state, state->cursor-1, 1);
13282  --state->cursor;
13283  }
13284  }
13285  state->has_preferred_x = 0;
13286  break;
13287 
13288  case NK_KEY_TEXT_START:
13289  if (shift_mod) {
13290  nk_textedit_prep_selection_at_cursor(state);
13291  state->cursor = state->select_end = 0;
13292  state->has_preferred_x = 0;
13293  } else {
13294  state->cursor = state->select_start = state->select_end = 0;
13295  state->has_preferred_x = 0;
13296  }
13297  break;
13298 
13299  case NK_KEY_TEXT_END:
13300  if (shift_mod) {
13301  nk_textedit_prep_selection_at_cursor(state);
13302  state->cursor = state->select_end = state->string.len;
13303  state->has_preferred_x = 0;
13304  } else {
13305  state->cursor = state->string.len;
13306  state->select_start = state->select_end = 0;
13307  state->has_preferred_x = 0;
13308  }
13309  break;
13310 
13311  case NK_KEY_TEXT_LINE_START: {
13312  if (shift_mod) {
13313  struct nk_text_find find;
13314  nk_textedit_clamp(state);
13315  nk_textedit_prep_selection_at_cursor(state);
13316  if (state->string.len && state->cursor == state->string.len)
13317  --state->cursor;
13318  nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
13319  font, row_height);
13320  state->cursor = state->select_end = find.first_char;
13321  state->has_preferred_x = 0;
13322  } else {
13323  struct nk_text_find find;
13324  if (state->string.len && state->cursor == state->string.len)
13325  --state->cursor;
13326  nk_textedit_clamp(state);
13327  nk_textedit_move_to_first(state);
13328  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13329  font, row_height);
13330  state->cursor = find.first_char;
13331  state->has_preferred_x = 0;
13332  }
13333  } break;
13334 
13335  case NK_KEY_TEXT_LINE_END: {
13336  if (shift_mod) {
13337  struct nk_text_find find;
13338  nk_textedit_clamp(state);
13339  nk_textedit_prep_selection_at_cursor(state);
13340  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13341  font, row_height);
13342  state->has_preferred_x = 0;
13343  state->cursor = find.first_char + find.length;
13344  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
13345  --state->cursor;
13346  state->select_end = state->cursor;
13347  } else {
13348  struct nk_text_find find;
13349  nk_textedit_clamp(state);
13350  nk_textedit_move_to_first(state);
13351  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13352  font, row_height);
13353 
13354  state->has_preferred_x = 0;
13355  state->cursor = find.first_char + find.length;
13356  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
13357  --state->cursor;
13358  }} break;
13359  }
13360 }
13361 
13362 NK_INTERN void
13363 nk_textedit_flush_redo(struct nk_text_undo_state *state)
13364 {
13367 }
13368 
13369 NK_INTERN void
13370 nk_textedit_discard_undo(struct nk_text_undo_state *state)
13371 {
13372  /* discard the oldest entry in the undo list */
13373  if (state->undo_point > 0) {
13374  /* if the 0th undo state has characters, clean those up */
13375  if (state->undo_rec[0].char_storage >= 0) {
13376  int n = state->undo_rec[0].insert_length, i;
13377  /* delete n characters from all other records */
13378  state->undo_char_point = (short)(state->undo_char_point - n);
13379  NK_MEMCPY(state->undo_char, state->undo_char + n,
13380  (nk_size)state->undo_char_point*sizeof(nk_rune));
13381  for (i=0; i < state->undo_point; ++i) {
13382  if (state->undo_rec[i].char_storage >= 0)
13383  state->undo_rec[i].char_storage = (short)
13384  (state->undo_rec[i].char_storage - n);
13385  }
13386  }
13387  --state->undo_point;
13388  NK_MEMCPY(state->undo_rec, state->undo_rec+1,
13389  (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
13390  }
13391 }
13392 
13393 NK_INTERN void
13394 nk_textedit_discard_redo(struct nk_text_undo_state *state)
13395 {
13396 /* discard the oldest entry in the redo list--it's bad if this
13397  ever happens, but because undo & redo have to store the actual
13398  characters in different cases, the redo character buffer can
13399  fill up even though the undo buffer didn't */
13400  nk_size num;
13401  int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
13402  if (state->redo_point <= k) {
13403  /* if the k'th undo state has characters, clean those up */
13404  if (state->undo_rec[k].char_storage >= 0) {
13405  int n = state->undo_rec[k].insert_length, i;
13406  /* delete n characters from all other records */
13407  state->redo_char_point = (short)(state->redo_char_point + n);
13409  NK_MEMCPY(state->undo_char + state->redo_char_point,
13410  state->undo_char + state->redo_char_point-n, num * sizeof(char));
13411  for (i = state->redo_point; i < k; ++i) {
13412  if (state->undo_rec[i].char_storage >= 0) {
13413  state->undo_rec[i].char_storage = (short)
13414  (state->undo_rec[i].char_storage + n);
13415  }
13416  }
13417  }
13418  ++state->redo_point;
13419  num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
13420  if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
13421  state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
13422  }
13423 }
13424 
13426 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
13427 {
13428  /* any time we create a new undo record, we discard redo*/
13429  nk_textedit_flush_redo(state);
13430 
13431  /* if we have no free records, we have to make room,
13432  * by sliding the existing records down */
13433  if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
13434  nk_textedit_discard_undo(state);
13435 
13436  /* if the characters to store won't possibly fit in the buffer,
13437  * we can't undo */
13438  if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
13439  state->undo_point = 0;
13440  state->undo_char_point = 0;
13441  return 0;
13442  }
13443 
13444  /* if we don't have enough free characters in the buffer,
13445  * we have to make room */
13446  while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
13447  nk_textedit_discard_undo(state);
13448  return &state->undo_rec[state->undo_point++];
13449 }
13450 
13451 NK_INTERN nk_rune*
13452 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
13453  int insert_len, int delete_len)
13454 {
13455  struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
13456  if (r == 0)
13457  return 0;
13458 
13459  r->where = pos;
13460  r->insert_length = (short) insert_len;
13461  r->delete_length = (short) delete_len;
13462 
13463  if (insert_len == 0) {
13464  r->char_storage = -1;
13465  return 0;
13466  } else {
13467  r->char_storage = state->undo_char_point;
13468  state->undo_char_point = (short)(state->undo_char_point + insert_len);
13469  return &state->undo_char[r->char_storage];
13470  }
13471 }
13472 
13473 NK_API void
13474 nk_textedit_undo(struct nk_text_edit *state)
13475 {
13476  struct nk_text_undo_state *s = &state->undo;
13477  struct nk_text_undo_record u, *r;
13478  if (s->undo_point == 0)
13479  return;
13480 
13481  /* we need to do two things: apply the undo record, and create a redo record */
13482  u = s->undo_rec[s->undo_point-1];
13483  r = &s->undo_rec[s->redo_point-1];
13484  r->char_storage = -1;
13485 
13486  r->insert_length = u.delete_length;
13487  r->delete_length = u.insert_length;
13488  r->where = u.where;
13489 
13490  if (u.delete_length)
13491  {
13492  /* if the undo record says to delete characters, then the redo record will
13493  need to re-insert the characters that get deleted, so we need to store
13494  them.
13495  there are three cases:
13496  - there's enough room to store the characters
13497  - characters stored for *redoing* don't leave room for redo
13498  - characters stored for *undoing* don't leave room for redo
13499  if the last is true, we have to bail */
13500  if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
13501  /* the undo records take up too much character space; there's no space
13502  * to store the redo characters */
13503  r->insert_length = 0;
13504  } else {
13505  int i;
13506  /* there's definitely room to store the characters eventually */
13507  while (s->undo_char_point + u.delete_length > s->redo_char_point) {
13508  /* there's currently not enough room, so discard a redo record */
13509  nk_textedit_discard_redo(s);
13510  /* should never happen: */
13512  return;
13513  }
13514 
13515  r = &s->undo_rec[s->redo_point-1];
13516  r->char_storage = (short)(s->redo_char_point - u.delete_length);
13517  s->redo_char_point = (short)(s->redo_char_point - u.delete_length);
13518 
13519  /* now save the characters */
13520  for (i=0; i < u.delete_length; ++i)
13521  s->undo_char[r->char_storage + i] =
13522  nk_str_rune_at(&state->string, u.where + i);
13523  }
13524  /* now we can carry out the deletion */
13525  nk_str_delete_runes(&state->string, u.where, u.delete_length);
13526  }
13527 
13528  /* check type of recorded action: */
13529  if (u.insert_length) {
13530  /* easy case: was a deletion, so we need to insert n characters */
13531  nk_str_insert_text_runes(&state->string, u.where,
13532  &s->undo_char[u.char_storage], u.insert_length);
13533  s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
13534  }
13535  state->cursor = (short)(u.where + u.insert_length);
13536 
13537  s->undo_point--;
13538  s->redo_point--;
13539 }
13540 
13541 NK_API void
13542 nk_textedit_redo(struct nk_text_edit *state)
13543 {
13544  struct nk_text_undo_state *s = &state->undo;
13545  struct nk_text_undo_record *u, r;
13547  return;
13548 
13549  /* we need to do two things: apply the redo record, and create an undo record */
13550  u = &s->undo_rec[s->undo_point];
13551  r = s->undo_rec[s->redo_point];
13552 
13553  /* we KNOW there must be room for the undo record, because the redo record
13554  was derived from an undo record */
13557  u->where = r.where;
13558  u->char_storage = -1;
13559 
13560  if (r.delete_length) {
13561  /* the redo record requires us to delete characters, so the undo record
13562  needs to store the characters */
13563  if (s->undo_char_point + u->insert_length > s->redo_char_point) {
13564  u->insert_length = 0;
13565  u->delete_length = 0;
13566  } else {
13567  int i;
13568  u->char_storage = s->undo_char_point;
13569  s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
13570 
13571  /* now save the characters */
13572  for (i=0; i < u->insert_length; ++i) {
13573  s->undo_char[u->char_storage + i] =
13574  nk_str_rune_at(&state->string, u->where + i);
13575  }
13576  }
13578  }
13579 
13580  if (r.insert_length) {
13581  /* easy case: need to insert n characters */
13584  }
13585  state->cursor = r.where + r.insert_length;
13586 
13587  s->undo_point++;
13588  s->redo_point++;
13589 }
13590 
13591 NK_INTERN void
13592 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
13593 {
13594  nk_textedit_createundo(&state->undo, where, 0, length);
13595 }
13596 
13597 NK_INTERN void
13598 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
13599 {
13600  int i;
13601  nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
13602  if (p) {
13603  for (i=0; i < length; ++i)
13604  p[i] = nk_str_rune_at(&state->string, where+i);
13605  }
13606 }
13607 
13608 NK_INTERN void
13609 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
13610  int old_length, int new_length)
13611 {
13612  int i;
13613  nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
13614  if (p) {
13615  for (i=0; i < old_length; ++i)
13616  p[i] = nk_str_rune_at(&state->string, where+i);
13617  }
13618 }
13619 
13620 NK_INTERN void
13621 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
13622  nk_plugin_filter filter)
13623 {
13624  /* reset the state to default */
13625  state->undo.undo_point = 0;
13626  state->undo.undo_char_point = 0;
13629  state->select_end = state->select_start = 0;
13630  state->cursor = 0;
13631  state->has_preferred_x = 0;
13632  state->preferred_x = 0;
13633  state->cursor_at_end_of_line = 0;
13634  state->initialized = 1;
13635  state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
13636  state->mode = NK_TEXT_EDIT_MODE_VIEW;
13637  state->filter = filter;
13638  state->scrollbar = nk_vec2(0,0);
13639 }
13640 
13641 NK_API void
13642 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
13643 {
13644  NK_ASSERT(state);
13645  NK_ASSERT(memory);
13646  if (!state || !memory || !size) return;
13647  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13648  nk_str_init_fixed(&state->string, memory, size);
13649 }
13650 
13651 NK_API void
13652 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size)
13653 {
13654  NK_ASSERT(state);
13655  NK_ASSERT(alloc);
13656  if (!state || !alloc) return;
13657  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13658  nk_str_init(&state->string, alloc, size);
13659 }
13660 
13661 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
13662 NK_API void
13663 nk_textedit_init_default(struct nk_text_edit *state)
13664 {
13665  NK_ASSERT(state);
13666  if (!state) return;
13667  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13668  nk_str_init_default(&state->string);
13669 }
13670 #endif
13671 
13672 NK_API void
13673 nk_textedit_select_all(struct nk_text_edit *state)
13674 {
13675  NK_ASSERT(state);
13676  state->select_start = 0;
13677  state->select_end = state->string.len;
13678 }
13679 
13680 NK_API void
13681 nk_textedit_free(struct nk_text_edit *state)
13682 {
13683  NK_ASSERT(state);
13684  if (!state) return;
13685  nk_str_free(&state->string);
13686 }
13687 
13688 /* ===============================================================
13689  *
13690  * TEXT WIDGET
13691  *
13692  * ===============================================================*/
13693 #define nk_widget_state_reset(s)\
13694  if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
13695  (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
13696  else (*(s)) = NK_WIDGET_STATE_INACTIVE;
13697 
13698 struct nk_text {
13699  struct nk_vec2 padding;
13700  struct nk_color background;
13701  struct nk_color text;
13702 };
13703 
13704 NK_INTERN void
13705 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
13706  const char *string, int len, const struct nk_text *t,
13707  nk_flags a, const struct nk_user_font *f)
13708 {
13709  struct nk_rect label;
13710  float text_width;
13711 
13712  NK_ASSERT(o);
13713  NK_ASSERT(t);
13714  if (!o || !t) return;
13715 
13716  b.h = NK_MAX(b.h, 2 * t->padding.y);
13717  label.x = 0; label.w = 0;
13718  label.y = b.y + t->padding.y;
13719  label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
13720 
13721  text_width = f->width(f->userdata, f->height, (const char*)string, len);
13722  text_width += (2.0f * t->padding.x);
13723 
13724  /* align in x-axis */
13725  if (a & NK_TEXT_ALIGN_LEFT) {
13726  label.x = b.x + t->padding.x;
13727  label.w = NK_MAX(0, b.w - 2 * t->padding.x);
13728  } else if (a & NK_TEXT_ALIGN_CENTERED) {
13729  label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
13730  label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
13731  label.x = NK_MAX(b.x + t->padding.x, label.x);
13732  label.w = NK_MIN(b.x + b.w, label.x + label.w);
13733  if (label.w >= label.x) label.w -= label.x;
13734  } else if (a & NK_TEXT_ALIGN_RIGHT) {
13735  label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
13736  label.w = (float)text_width + 2 * t->padding.x;
13737  } else return;
13738 
13739  /* align in y-axis */
13740  if (a & NK_TEXT_ALIGN_MIDDLE) {
13741  label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
13742  label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
13743  } else if (a & NK_TEXT_ALIGN_BOTTOM) {
13744  label.y = b.y + b.h - f->height;
13745  label.h = f->height;
13746  }
13747  nk_draw_text(o, label, (const char*)string,
13748  len, f, t->background, t->text);
13749 }
13750 
13751 NK_INTERN void
13752 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
13753  const char *string, int len, const struct nk_text *t,
13754  const struct nk_user_font *f)
13755 {
13756  float width;
13757  int glyphs = 0;
13758  int fitting = 0;
13759  int done = 0;
13760  struct nk_rect line;
13761  struct nk_text text;
13762  NK_INTERN nk_rune seperator[] = {' '};
13763 
13764  NK_ASSERT(o);
13765  NK_ASSERT(t);
13766  if (!o || !t) return;
13767 
13768  text.padding = nk_vec2(0,0);
13769  text.background = t->background;
13770  text.text = t->text;
13771 
13772  b.w = NK_MAX(b.w, 2 * t->padding.x);
13773  b.h = NK_MAX(b.h, 2 * t->padding.y);
13774  b.h = b.h - 2 * t->padding.y;
13775 
13776  line.x = b.x + t->padding.x;
13777  line.y = b.y + t->padding.y;
13778  line.w = b.w - 2 * t->padding.x;
13779  line.h = 2 * t->padding.y + f->height;
13780 
13781  fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
13782  while (done < len) {
13783  if (!fitting || line.y + line.h >= (b.y + b.h)) break;
13784  nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
13785  done += fitting;
13786  line.y += f->height + 2 * t->padding.y;
13787  fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
13788  }
13789 }
13790 
13791 /* ===============================================================
13792  *
13793  * BUTTON
13794  *
13795  * ===============================================================*/
13796 NK_INTERN void
13797 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
13798  struct nk_rect content, struct nk_color background, struct nk_color foreground,
13799  float border_width, const struct nk_user_font *font)
13800 {
13801  switch (type) {
13802  case NK_SYMBOL_X:
13803  case NK_SYMBOL_UNDERSCORE:
13804  case NK_SYMBOL_PLUS:
13805  case NK_SYMBOL_MINUS: {
13806  /* single character text symbol */
13807  const char *X = (type == NK_SYMBOL_X) ? "x":
13808  (type == NK_SYMBOL_UNDERSCORE) ? "_":
13809  (type == NK_SYMBOL_PLUS) ? "+": "-";
13810  struct nk_text text;
13811  text.padding = nk_vec2(0,0);
13812  text.background = background;
13813  text.text = foreground;
13814  nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
13815  } break;
13818  case NK_SYMBOL_RECT_SOLID:
13819  case NK_SYMBOL_RECT_OUTLINE: {
13820  /* simple empty/filled shapes */
13821  if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
13822  nk_fill_rect(out, content, 0, foreground);
13823  if (type == NK_SYMBOL_RECT_OUTLINE)
13824  nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
13825  } else {
13826  nk_fill_circle(out, content, foreground);
13827  if (type == NK_SYMBOL_CIRCLE_OUTLINE)
13828  nk_fill_circle(out, nk_shrink_rect(content, 1), background);
13829  }
13830  } break;
13831  case NK_SYMBOL_TRIANGLE_UP:
13834  case NK_SYMBOL_TRIANGLE_RIGHT: {
13835  enum nk_heading heading;
13836  struct nk_vec2 points[3];
13837  heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
13838  (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
13839  (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
13840  nk_triangle_from_direction(points, content, 0, 0, heading);
13841  nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
13842  points[2].x, points[2].y, foreground);
13843  } break;
13844  default:
13845  case NK_SYMBOL_NONE:
13846  case NK_SYMBOL_MAX: break;
13847  }
13848 }
13849 
13850 NK_INTERN int
13851 nk_button_behavior(nk_flags *state, struct nk_rect r,
13852  const struct nk_input *i, enum nk_button_behavior behavior)
13853 {
13854  int ret = 0;
13855  nk_widget_state_reset(state);
13856  if (!i) return 0;
13857  if (nk_input_is_mouse_hovering_rect(i, r)) {
13858  *state = NK_WIDGET_STATE_HOVERED;
13860  *state = NK_WIDGET_STATE_ACTIVE;
13862  ret = (behavior != NK_BUTTON_DEFAULT) ?
13864 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
13866 #else
13868 #endif
13869  }
13870  }
13872  *state |= NK_WIDGET_STATE_ENTERED;
13873  else if (nk_input_is_mouse_prev_hovering_rect(i, r))
13874  *state |= NK_WIDGET_STATE_LEFT;
13875  return ret;
13876 }
13877 
13878 NK_INTERN const struct nk_style_item*
13879 nk_draw_button(struct nk_command_buffer *out,
13880  const struct nk_rect *bounds, nk_flags state,
13881  const struct nk_style_button *style)
13882 {
13883  const struct nk_style_item *background;
13884  if (state & NK_WIDGET_STATE_HOVER)
13885  background = &style->hover;
13886  else if (state & NK_WIDGET_STATE_ACTIVED)
13887  background = &style->active;
13888  else background = &style->normal;
13889 
13890  if (background->type == NK_STYLE_ITEM_IMAGE) {
13891  nk_draw_image(out, *bounds, &background->data.image, nk_white);
13892  } else {
13893  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
13894  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
13895  }
13896  return background;
13897 }
13898 
13899 NK_INTERN int
13900 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
13901  const struct nk_style_button *style, const struct nk_input *in,
13902  enum nk_button_behavior behavior, struct nk_rect *content)
13903 {
13904  struct nk_rect bounds;
13905  NK_ASSERT(style);
13906  NK_ASSERT(state);
13907  NK_ASSERT(out);
13908  if (!out || !style)
13909  return nk_false;
13910 
13911  /* calculate button content space */
13912  content->x = r.x + style->padding.x + style->border + style->rounding;
13913  content->y = r.y + style->padding.y + style->border + style->rounding;
13914  content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
13915  content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
13916 
13917  /* execute button behavior */
13918  bounds.x = r.x - style->touch_padding.x;
13919  bounds.y = r.y - style->touch_padding.y;
13920  bounds.w = r.w + 2 * style->touch_padding.x;
13921  bounds.h = r.h + 2 * style->touch_padding.y;
13922  return nk_button_behavior(state, bounds, in, behavior);
13923 }
13924 
13925 NK_INTERN void
13926 nk_draw_button_text(struct nk_command_buffer *out,
13927  const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
13928  const struct nk_style_button *style, const char *txt, int len,
13929  nk_flags text_alignment, const struct nk_user_font *font)
13930 {
13931  struct nk_text text;
13932  const struct nk_style_item *background;
13933  background = nk_draw_button(out, bounds, state, style);
13934 
13935  /* select correct colors/images */
13936  if (background->type == NK_STYLE_ITEM_COLOR)
13937  text.background = background->data.color;
13938  else text.background = style->text_background;
13939  if (state & NK_WIDGET_STATE_HOVER)
13940  text.text = style->text_hover;
13941  else if (state & NK_WIDGET_STATE_ACTIVED)
13942  text.text = style->text_active;
13943  else text.text = style->text_normal;
13944 
13945  text.padding = nk_vec2(0,0);
13946  nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
13947 }
13948 
13949 NK_INTERN int
13950 nk_do_button_text(nk_flags *state,
13951  struct nk_command_buffer *out, struct nk_rect bounds,
13952  const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
13953  const struct nk_style_button *style, const struct nk_input *in,
13954  const struct nk_user_font *font)
13955 {
13956  struct nk_rect content;
13957  int ret = nk_false;
13958 
13959  NK_ASSERT(state);
13960  NK_ASSERT(style);
13961  NK_ASSERT(out);
13962  NK_ASSERT(string);
13963  NK_ASSERT(font);
13964  if (!out || !style || !font || !string)
13965  return nk_false;
13966 
13967  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
13968  if (style->draw_begin) style->draw_begin(out, style->userdata);
13969  nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
13970  if (style->draw_end) style->draw_end(out, style->userdata);
13971  return ret;
13972 }
13973 
13974 NK_INTERN void
13975 nk_draw_button_symbol(struct nk_command_buffer *out,
13976  const struct nk_rect *bounds, const struct nk_rect *content,
13977  nk_flags state, const struct nk_style_button *style,
13978  enum nk_symbol_type type, const struct nk_user_font *font)
13979 {
13980  struct nk_color sym, bg;
13981  const struct nk_style_item *background;
13982 
13983  /* select correct colors/images */
13984  background = nk_draw_button(out, bounds, state, style);
13985  if (background->type == NK_STYLE_ITEM_COLOR)
13986  bg = background->data.color;
13987  else bg = style->text_background;
13988 
13989  if (state & NK_WIDGET_STATE_HOVER)
13990  sym = style->text_hover;
13991  else if (state & NK_WIDGET_STATE_ACTIVED)
13992  sym = style->text_active;
13993  else sym = style->text_normal;
13994  nk_draw_symbol(out, type, *content, bg, sym, 1, font);
13995 }
13996 
13997 NK_INTERN int
13998 nk_do_button_symbol(nk_flags *state,
13999  struct nk_command_buffer *out, struct nk_rect bounds,
14000  enum nk_symbol_type symbol, enum nk_button_behavior behavior,
14001  const struct nk_style_button *style, const struct nk_input *in,
14002  const struct nk_user_font *font)
14003 {
14004  int ret;
14005  struct nk_rect content;
14006 
14007  NK_ASSERT(state);
14008  NK_ASSERT(style);
14009  NK_ASSERT(font);
14010  NK_ASSERT(out);
14011  if (!out || !style || !font || !state)
14012  return nk_false;
14013 
14014  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14015  if (style->draw_begin) style->draw_begin(out, style->userdata);
14016  nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
14017  if (style->draw_end) style->draw_end(out, style->userdata);
14018  return ret;
14019 }
14020 
14021 NK_INTERN void
14022 nk_draw_button_image(struct nk_command_buffer *out,
14023  const struct nk_rect *bounds, const struct nk_rect *content,
14024  nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
14025 {
14026  nk_draw_button(out, bounds, state, style);
14027  nk_draw_image(out, *content, img, nk_white);
14028 }
14029 
14030 NK_INTERN int
14031 nk_do_button_image(nk_flags *state,
14032  struct nk_command_buffer *out, struct nk_rect bounds,
14033  struct nk_image img, enum nk_button_behavior b,
14034  const struct nk_style_button *style, const struct nk_input *in)
14035 {
14036  int ret;
14037  struct nk_rect content;
14038 
14039  NK_ASSERT(state);
14040  NK_ASSERT(style);
14041  NK_ASSERT(out);
14042  if (!out || !style || !state)
14043  return nk_false;
14044 
14045  ret = nk_do_button(state, out, bounds, style, in, b, &content);
14046  content.x += style->image_padding.x;
14047  content.y += style->image_padding.y;
14048  content.w -= 2 * style->image_padding.x;
14049  content.h -= 2 * style->image_padding.y;
14050 
14051  if (style->draw_begin) style->draw_begin(out, style->userdata);
14052  nk_draw_button_image(out, &bounds, &content, *state, style, &img);
14053  if (style->draw_end) style->draw_end(out, style->userdata);
14054  return ret;
14055 }
14056 
14057 NK_INTERN void
14058 nk_draw_button_text_symbol(struct nk_command_buffer *out,
14059  const struct nk_rect *bounds, const struct nk_rect *label,
14060  const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
14061  const char *str, int len, enum nk_symbol_type type,
14062  const struct nk_user_font *font)
14063 {
14064  struct nk_color sym;
14065  struct nk_text text;
14066  const struct nk_style_item *background;
14067 
14068  /* select correct background colors/images */
14069  background = nk_draw_button(out, bounds, state, style);
14070  if (background->type == NK_STYLE_ITEM_COLOR)
14071  text.background = background->data.color;
14072  else text.background = style->text_background;
14073 
14074  /* select correct text colors */
14075  if (state & NK_WIDGET_STATE_HOVER) {
14076  sym = style->text_hover;
14077  text.text = style->text_hover;
14078  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14079  sym = style->text_active;
14080  text.text = style->text_active;
14081  } else {
14082  sym = style->text_normal;
14083  text.text = style->text_normal;
14084  }
14085 
14086  text.padding = nk_vec2(0,0);
14087  nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
14088  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
14089 }
14090 
14091 NK_INTERN int
14092 nk_do_button_text_symbol(nk_flags *state,
14093  struct nk_command_buffer *out, struct nk_rect bounds,
14094  enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
14095  enum nk_button_behavior behavior, const struct nk_style_button *style,
14096  const struct nk_user_font *font, const struct nk_input *in)
14097 {
14098  int ret;
14099  struct nk_rect tri = {0,0,0,0};
14100  struct nk_rect content;
14101 
14102  NK_ASSERT(style);
14103  NK_ASSERT(out);
14104  NK_ASSERT(font);
14105  if (!out || !style || !font)
14106  return nk_false;
14107 
14108  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14109  tri.y = content.y + (content.h/2) - font->height/2;
14110  tri.w = font->height; tri.h = font->height;
14111  if (align & NK_TEXT_ALIGN_LEFT) {
14112  tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
14113  tri.x = NK_MAX(tri.x, 0);
14114  } else tri.x = content.x + 2 * style->padding.x;
14115 
14116  /* draw button */
14117  if (style->draw_begin) style->draw_begin(out, style->userdata);
14118  nk_draw_button_text_symbol(out, &bounds, &content, &tri,
14119  *state, style, str, len, symbol, font);
14120  if (style->draw_end) style->draw_end(out, style->userdata);
14121  return ret;
14122 }
14123 
14124 NK_INTERN void
14125 nk_draw_button_text_image(struct nk_command_buffer *out,
14126  const struct nk_rect *bounds, const struct nk_rect *label,
14127  const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
14128  const char *str, int len, const struct nk_user_font *font,
14129  const struct nk_image *img)
14130 {
14131  struct nk_text text;
14132  const struct nk_style_item *background;
14133  background = nk_draw_button(out, bounds, state, style);
14134 
14135  /* select correct colors */
14136  if (background->type == NK_STYLE_ITEM_COLOR)
14137  text.background = background->data.color;
14138  else text.background = style->text_background;
14139  if (state & NK_WIDGET_STATE_HOVER)
14140  text.text = style->text_hover;
14141  else if (state & NK_WIDGET_STATE_ACTIVED)
14142  text.text = style->text_active;
14143  else text.text = style->text_normal;
14144 
14145  text.padding = nk_vec2(0,0);
14146  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
14147  nk_draw_image(out, *image, img, nk_white);
14148 }
14149 
14150 NK_INTERN int
14151 nk_do_button_text_image(nk_flags *state,
14152  struct nk_command_buffer *out, struct nk_rect bounds,
14153  struct nk_image img, const char* str, int len, nk_flags align,
14154  enum nk_button_behavior behavior, const struct nk_style_button *style,
14155  const struct nk_user_font *font, const struct nk_input *in)
14156 {
14157  int ret;
14158  struct nk_rect icon;
14159  struct nk_rect content;
14160 
14161  NK_ASSERT(style);
14162  NK_ASSERT(state);
14163  NK_ASSERT(font);
14164  NK_ASSERT(out);
14165  if (!out || !font || !style || !str)
14166  return nk_false;
14167 
14168  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14169  icon.y = bounds.y + style->padding.y;
14170  icon.w = icon.h = bounds.h - 2 * style->padding.y;
14171  if (align & NK_TEXT_ALIGN_LEFT) {
14172  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
14173  icon.x = NK_MAX(icon.x, 0);
14174  } else icon.x = bounds.x + 2 * style->padding.x;
14175 
14176  icon.x += style->image_padding.x;
14177  icon.y += style->image_padding.y;
14178  icon.w -= 2 * style->image_padding.x;
14179  icon.h -= 2 * style->image_padding.y;
14180 
14181  if (style->draw_begin) style->draw_begin(out, style->userdata);
14182  nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
14183  if (style->draw_end) style->draw_end(out, style->userdata);
14184  return ret;
14185 }
14186 
14187 /* ===============================================================
14188  *
14189  * TOGGLE
14190  *
14191  * ===============================================================*/
14192 enum nk_toggle_type {
14193  NK_TOGGLE_CHECK,
14194  NK_TOGGLE_OPTION
14195 };
14196 
14197 NK_INTERN int
14198 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
14199  nk_flags *state, int active)
14200 {
14201  nk_widget_state_reset(state);
14202  if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
14203  *state = NK_WIDGET_STATE_ACTIVE;
14204  active = !active;
14205  }
14206  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
14207  *state |= NK_WIDGET_STATE_ENTERED;
14208  else if (nk_input_is_mouse_prev_hovering_rect(in, select))
14209  *state |= NK_WIDGET_STATE_LEFT;
14210  return active;
14211 }
14212 
14213 NK_INTERN void
14214 nk_draw_checkbox(struct nk_command_buffer *out,
14215  nk_flags state, const struct nk_style_toggle *style, int active,
14216  const struct nk_rect *label, const struct nk_rect *selector,
14217  const struct nk_rect *cursors, const char *string, int len,
14218  const struct nk_user_font *font)
14219 {
14220  const struct nk_style_item *background;
14221  const struct nk_style_item *cursor;
14222  struct nk_text text;
14223 
14224  /* select correct colors/images */
14225  if (state & NK_WIDGET_STATE_HOVER) {
14226  background = &style->hover;
14227  cursor = &style->cursor_hover;
14228  text.text = style->text_hover;
14229  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14230  background = &style->hover;
14231  cursor = &style->cursor_hover;
14232  text.text = style->text_active;
14233  } else {
14234  background = &style->normal;
14235  cursor = &style->cursor_normal;
14236  text.text = style->text_normal;
14237  }
14238 
14239  /* draw background and cursor */
14240  if (background->type == NK_STYLE_ITEM_COLOR) {
14241  nk_fill_rect(out, *selector, 0, style->border_color);
14242  nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
14243  } else nk_draw_image(out, *selector, &background->data.image, nk_white);
14244  if (active) {
14245  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14246  nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
14247  else nk_fill_rect(out, *cursors, 0, cursor->data.color);
14248  }
14249 
14250  text.padding.x = 0;
14251  text.padding.y = 0;
14252  text.background = style->text_background;
14253  nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
14254 }
14255 
14256 NK_INTERN void
14257 nk_draw_option(struct nk_command_buffer *out,
14258  nk_flags state, const struct nk_style_toggle *style, int active,
14259  const struct nk_rect *label, const struct nk_rect *selector,
14260  const struct nk_rect *cursors, const char *string, int len,
14261  const struct nk_user_font *font)
14262 {
14263  const struct nk_style_item *background;
14264  const struct nk_style_item *cursor;
14265  struct nk_text text;
14266 
14267  /* select correct colors/images */
14268  if (state & NK_WIDGET_STATE_HOVER) {
14269  background = &style->hover;
14270  cursor = &style->cursor_hover;
14271  text.text = style->text_hover;
14272  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14273  background = &style->hover;
14274  cursor = &style->cursor_hover;
14275  text.text = style->text_active;
14276  } else {
14277  background = &style->normal;
14278  cursor = &style->cursor_normal;
14279  text.text = style->text_normal;
14280  }
14281 
14282  /* draw background and cursor */
14283  if (background->type == NK_STYLE_ITEM_COLOR) {
14284  nk_fill_circle(out, *selector, style->border_color);
14285  nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
14286  } else nk_draw_image(out, *selector, &background->data.image, nk_white);
14287  if (active) {
14288  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14289  nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
14290  else nk_fill_circle(out, *cursors, cursor->data.color);
14291  }
14292 
14293  text.padding.x = 0;
14294  text.padding.y = 0;
14295  text.background = style->text_background;
14296  nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
14297 }
14298 
14299 NK_INTERN int
14300 nk_do_toggle(nk_flags *state,
14301  struct nk_command_buffer *out, struct nk_rect r,
14302  int *active, const char *str, int len, enum nk_toggle_type type,
14303  const struct nk_style_toggle *style, const struct nk_input *in,
14304  const struct nk_user_font *font)
14305 {
14306  int was_active;
14307  struct nk_rect bounds;
14308  struct nk_rect select;
14309  struct nk_rect cursor;
14310  struct nk_rect label;
14311 
14312  NK_ASSERT(style);
14313  NK_ASSERT(out);
14314  NK_ASSERT(font);
14315  if (!out || !style || !font || !active)
14316  return 0;
14317 
14318  r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
14319  r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
14320 
14321  /* add additional touch padding for touch screen devices */
14322  bounds.x = r.x - style->touch_padding.x;
14323  bounds.y = r.y - style->touch_padding.y;
14324  bounds.w = r.w + 2 * style->touch_padding.x;
14325  bounds.h = r.h + 2 * style->touch_padding.y;
14326 
14327  /* calculate the selector space */
14328  select.w = font->height;
14329  select.h = select.w;
14330  select.y = r.y + r.h/2.0f - select.h/2.0f;
14331  select.x = r.x;
14332 
14333  /* calculate the bounds of the cursor inside the selector */
14334  cursor.x = select.x + style->padding.x + style->border;
14335  cursor.y = select.y + style->padding.y + style->border;
14336  cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
14337  cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
14338 
14339  /* label behind the selector */
14340  label.x = select.x + select.w + style->spacing;
14341  label.y = select.y;
14342  label.w = NK_MAX(r.x + r.w, label.x) - label.x;
14343  label.h = select.w;
14344 
14345  /* update selector */
14346  was_active = *active;
14347  *active = nk_toggle_behavior(in, bounds, state, *active);
14348 
14349  /* draw selector */
14350  if (style->draw_begin)
14351  style->draw_begin(out, style->userdata);
14352  if (type == NK_TOGGLE_CHECK) {
14353  nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
14354  } else {
14355  nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
14356  }
14357  if (style->draw_end)
14358  style->draw_end(out, style->userdata);
14359  return (was_active != *active);
14360 }
14361 
14362 /* ===============================================================
14363  *
14364  * SELECTABLE
14365  *
14366  * ===============================================================*/
14367 NK_INTERN void
14368 nk_draw_selectable(struct nk_command_buffer *out,
14369  nk_flags state, const struct nk_style_selectable *style, int active,
14370  const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img,
14371  const char *string, int len, nk_flags align, const struct nk_user_font *font)
14372 {
14373  const struct nk_style_item *background;
14374  struct nk_text text;
14375  text.padding = style->padding;
14376 
14377  /* select correct colors/images */
14378  if (!active) {
14379  if (state & NK_WIDGET_STATE_ACTIVED) {
14380  background = &style->pressed;
14381  text.text = style->text_pressed;
14382  } else if (state & NK_WIDGET_STATE_HOVER) {
14383  background = &style->hover;
14384  text.text = style->text_hover;
14385  } else {
14386  background = &style->normal;
14387  text.text = style->text_normal;
14388  }
14389  } else {
14390  if (state & NK_WIDGET_STATE_ACTIVED) {
14391  background = &style->pressed_active;
14392  text.text = style->text_pressed_active;
14393  } else if (state & NK_WIDGET_STATE_HOVER) {
14394  background = &style->hover_active;
14395  text.text = style->text_hover_active;
14396  } else {
14397  background = &style->normal_active;
14398  text.text = style->text_normal_active;
14399  }
14400  }
14401 
14402 
14403  /* draw selectable background and text */
14404  if (background->type == NK_STYLE_ITEM_IMAGE) {
14405  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14406  text.background = nk_rgba(0,0,0,0);
14407  } else {
14408  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14409  text.background = background->data.color;
14410  }
14411  if (img && icon) nk_draw_image(out, *icon, img, nk_white);
14412  nk_widget_text(out, *bounds, string, len, &text, align, font);
14413 }
14414 
14415 NK_INTERN int
14416 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
14417  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
14418  const struct nk_style_selectable *style, const struct nk_input *in,
14419  const struct nk_user_font *font)
14420 {
14421  int old_value;
14422  struct nk_rect touch;
14423 
14424  NK_ASSERT(state);
14425  NK_ASSERT(out);
14426  NK_ASSERT(str);
14427  NK_ASSERT(len);
14428  NK_ASSERT(value);
14429  NK_ASSERT(style);
14430  NK_ASSERT(font);
14431 
14432  if (!state || !out || !str || !len || !value || !style || !font) return 0;
14433  old_value = *value;
14434 
14435  /* remove padding */
14436  touch.x = bounds.x - style->touch_padding.x;
14437  touch.y = bounds.y - style->touch_padding.y;
14438  touch.w = bounds.w + style->touch_padding.x * 2;
14439  touch.h = bounds.h + style->touch_padding.y * 2;
14440 
14441  /* update button */
14442  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
14443  *value = !(*value);
14444 
14445  /* draw selectable */
14446  if (style->draw_begin) style->draw_begin(out, style->userdata);
14447  nk_draw_selectable(out, *state, style, *value, &bounds, 0,0, str, len, align, font);
14448  if (style->draw_end) style->draw_end(out, style->userdata);
14449  return old_value != *value;
14450 }
14451 
14452 NK_INTERN int
14453 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
14454  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
14455  const struct nk_image *img, const struct nk_style_selectable *style,
14456  const struct nk_input *in, const struct nk_user_font *font)
14457 {
14458  int old_value;
14459  struct nk_rect touch;
14460  struct nk_rect icon;
14461 
14462  NK_ASSERT(state);
14463  NK_ASSERT(out);
14464  NK_ASSERT(str);
14465  NK_ASSERT(len);
14466  NK_ASSERT(value);
14467  NK_ASSERT(style);
14468  NK_ASSERT(font);
14469 
14470  if (!state || !out || !str || !len || !value || !style || !font) return 0;
14471  old_value = *value;
14472 
14473  /* toggle behavior */
14474  touch.x = bounds.x - style->touch_padding.x;
14475  touch.y = bounds.y - style->touch_padding.y;
14476  touch.w = bounds.w + style->touch_padding.x * 2;
14477  touch.h = bounds.h + style->touch_padding.y * 2;
14478  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
14479  *value = !(*value);
14480 
14481  icon.y = bounds.y + style->padding.y;
14482  icon.w = icon.h = bounds.h - 2 * style->padding.y;
14483  if (align & NK_TEXT_ALIGN_LEFT) {
14484  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
14485  icon.x = NK_MAX(icon.x, 0);
14486  } else icon.x = bounds.x + 2 * style->padding.x;
14487 
14488  icon.x += style->image_padding.x;
14489  icon.y += style->image_padding.y;
14490  icon.w -= 2 * style->image_padding.x;
14491  icon.h -= 2 * style->image_padding.y;
14492 
14493  /* draw selectable */
14494  if (style->draw_begin) style->draw_begin(out, style->userdata);
14495  nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, str, len, align, font);
14496  if (style->draw_end) style->draw_end(out, style->userdata);
14497  return old_value != *value;
14498 }
14499 
14500 
14501 /* ===============================================================
14502  *
14503  * SLIDER
14504  *
14505  * ===============================================================*/
14506 NK_INTERN float
14507 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
14508  struct nk_rect *visual_cursor, struct nk_input *in,
14509  struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
14510  float slider_step, float slider_steps)
14511 {
14512  int left_mouse_down;
14513  int left_mouse_click_in_cursor;
14514 
14515  /* check if visual cursor is being dragged */
14516  nk_widget_state_reset(state);
14517  left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
14518  left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
14519  NK_BUTTON_LEFT, *visual_cursor, nk_true);
14520 
14521  if (left_mouse_down && left_mouse_click_in_cursor)
14522  {
14523  float ratio = 0;
14524  const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
14525  const float pxstep = bounds.w / slider_steps;
14526 
14527  /* only update value if the next slider step is reached */
14528  *state = NK_WIDGET_STATE_ACTIVE;
14529  if (NK_ABS(d) >= pxstep) {
14530  const float steps = (float)((int)(NK_ABS(d) / pxstep));
14531  slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
14532  slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
14533  ratio = (slider_value - slider_min)/slider_step;
14534  logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
14535  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
14536  }
14537  }
14538 
14539  /* slider widget state */
14540  if (nk_input_is_mouse_hovering_rect(in, bounds))
14541  *state = NK_WIDGET_STATE_HOVERED;
14542  if (*state & NK_WIDGET_STATE_HOVER &&
14544  *state |= NK_WIDGET_STATE_ENTERED;
14545  else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
14546  *state |= NK_WIDGET_STATE_LEFT;
14547  return slider_value;
14548 }
14549 
14550 NK_INTERN void
14551 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
14552  const struct nk_style_slider *style, const struct nk_rect *bounds,
14553  const struct nk_rect *visual_cursor, float min, float value, float max)
14554 {
14555  struct nk_rect fill;
14556  struct nk_rect bar;
14557  const struct nk_style_item *background;
14558 
14559  /* select correct slider images/colors */
14560  struct nk_color bar_color;
14561  const struct nk_style_item *cursor;
14562 
14563  NK_UNUSED(min);
14564  NK_UNUSED(max);
14565  NK_UNUSED(value);
14566 
14567  if (state & NK_WIDGET_STATE_ACTIVED) {
14568  background = &style->active;
14569  bar_color = style->bar_active;
14570  cursor = &style->cursor_active;
14571  } else if (state & NK_WIDGET_STATE_HOVER) {
14572  background = &style->hover;
14573  bar_color = style->bar_hover;
14574  cursor = &style->cursor_hover;
14575  } else {
14576  background = &style->normal;
14577  bar_color = style->bar_normal;
14578  cursor = &style->cursor_normal;
14579  }
14580 
14581  /* calculate slider background bar */
14582  bar.x = bounds->x;
14583  bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
14584  bar.w = bounds->w;
14585  bar.h = bounds->h/6;
14586 
14587  /* filled background bar style */
14588  fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
14589  fill.x = bar.x;
14590  fill.y = bar.y;
14591  fill.h = bar.h;
14592 
14593  /* draw background */
14594  if (background->type == NK_STYLE_ITEM_IMAGE) {
14595  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14596  } else {
14597  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14598  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14599  }
14600 
14601  /* draw slider bar */
14602  nk_fill_rect(out, bar, style->rounding, bar_color);
14603  nk_fill_rect(out, fill, style->rounding, style->bar_filled);
14604 
14605  /* draw cursor */
14606  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14607  nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
14608  else nk_fill_circle(out, *visual_cursor, cursor->data.color);
14609 }
14610 
14611 NK_INTERN float
14612 nk_do_slider(nk_flags *state,
14613  struct nk_command_buffer *out, struct nk_rect bounds,
14614  float min, float val, float max, float step,
14615  const struct nk_style_slider *style, struct nk_input *in,
14616  const struct nk_user_font *font)
14617 {
14618  float slider_range;
14619  float slider_min;
14620  float slider_max;
14621  float slider_value;
14622  float slider_steps;
14623  float cursor_offset;
14624 
14625  struct nk_rect visual_cursor;
14626  struct nk_rect logical_cursor;
14627 
14628  NK_ASSERT(style);
14629  NK_ASSERT(out);
14630  if (!out || !style)
14631  return 0;
14632 
14633  /* remove padding from slider bounds */
14634  bounds.x = bounds.x + style->padding.x;
14635  bounds.y = bounds.y + style->padding.y;
14636  bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
14637  bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
14638  bounds.w -= 2 * style->padding.x;
14639  bounds.h -= 2 * style->padding.y;
14640 
14641  /* optional buttons */
14642  if (style->show_buttons) {
14643  nk_flags ws;
14644  struct nk_rect button;
14645  button.y = bounds.y;
14646  button.w = bounds.h;
14647  button.h = bounds.h;
14648 
14649  /* decrement button */
14650  button.x = bounds.x;
14651  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
14652  &style->dec_button, in, font))
14653  val -= step;
14654 
14655  /* increment button */
14656  button.x = (bounds.x + bounds.w) - button.w;
14657  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
14658  &style->inc_button, in, font))
14659  val += step;
14660 
14661  bounds.x = bounds.x + button.w + style->spacing.x;
14662  bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
14663  }
14664 
14665  /* remove one cursor size to support visual cursor */
14666  bounds.x += style->cursor_size.x*0.5f;
14667  bounds.w -= style->cursor_size.x;
14668 
14669  /* make sure the provided values are correct */
14670  slider_max = NK_MAX(min, max);
14671  slider_min = NK_MIN(min, max);
14672  slider_value = NK_CLAMP(slider_min, val, slider_max);
14673  slider_range = slider_max - slider_min;
14674  slider_steps = slider_range / step;
14675  cursor_offset = (slider_value - slider_min) / step;
14676 
14677  /* calculate cursor
14678  Basically you have two cursors. One for visual representation and interaction
14679  and one for updating the actual cursor value. */
14680  logical_cursor.h = bounds.h;
14681  logical_cursor.w = bounds.w / slider_steps;
14682  logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
14683  logical_cursor.y = bounds.y;
14684 
14685  visual_cursor.h = style->cursor_size.y;
14686  visual_cursor.w = style->cursor_size.x;
14687  visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
14688  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
14689 
14690  slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
14691  in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
14692  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
14693 
14694  /* draw slider */
14695  if (style->draw_begin) style->draw_begin(out, style->userdata);
14696  nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
14697  if (style->draw_end) style->draw_end(out, style->userdata);
14698  return slider_value;
14699 }
14700 
14701 /* ===============================================================
14702  *
14703  * PROGRESSBAR
14704  *
14705  * ===============================================================*/
14706 NK_INTERN nk_size
14707 nk_progress_behavior(nk_flags *state, const struct nk_input *in,
14708  struct nk_rect r, nk_size max, nk_size value, int modifiable)
14709 {
14710  nk_widget_state_reset(state);
14711  if (in && modifiable && nk_input_is_mouse_hovering_rect(in, r)) {
14712  int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
14713  int left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
14714  NK_BUTTON_LEFT, r, nk_true);
14715 
14716  if (left_mouse_down && left_mouse_click_in_cursor) {
14717  float ratio = NK_MAX(0, (float)(in->mouse.pos.x - r.x)) / (float)r.w;
14718  value = (nk_size)NK_MAX(0,((float)max * ratio));
14719  *state = NK_WIDGET_STATE_ACTIVE;
14720  } else *state = NK_WIDGET_STATE_HOVERED;
14721  }
14722 
14723  /* set progressbar widget state */
14724  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r))
14725  *state |= NK_WIDGET_STATE_ENTERED;
14726  else if (nk_input_is_mouse_prev_hovering_rect(in, r))
14727  *state |= NK_WIDGET_STATE_LEFT;
14728 
14729  if (!max) return value;
14730  value = NK_MIN(value, max);
14731  return value;
14732 }
14733 
14734 NK_INTERN void
14735 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
14736  const struct nk_style_progress *style, const struct nk_rect *bounds,
14737  const struct nk_rect *scursor, nk_size value, nk_size max)
14738 {
14739  const struct nk_style_item *background;
14740  const struct nk_style_item *cursor;
14741 
14742  NK_UNUSED(max);
14743  NK_UNUSED(value);
14744 
14745  /* select correct colors/images to draw */
14746  if (state & NK_WIDGET_STATE_ACTIVED) {
14747  background = &style->active;
14748  cursor = &style->cursor_active;
14749  } else if (state & NK_WIDGET_STATE_HOVER){
14750  background = &style->hover;
14751  cursor = &style->cursor_hover;
14752  } else {
14753  background = &style->normal;
14754  cursor = &style->cursor_normal;
14755  }
14756 
14757  /* draw background */
14758  if (background->type == NK_STYLE_ITEM_COLOR) {
14759  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14760  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14761  } else nk_draw_image(out, *bounds, &background->data.image, nk_white);
14762 
14763  /* draw cursor */
14764  if (background->type == NK_STYLE_ITEM_COLOR) {
14765  nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
14766  nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
14767  } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
14768 }
14769 
14770 NK_INTERN nk_size
14771 nk_do_progress(nk_flags *state,
14772  struct nk_command_buffer *out, struct nk_rect bounds,
14773  nk_size value, nk_size max, int modifiable,
14774  const struct nk_style_progress *style, const struct nk_input *in)
14775 {
14776  float prog_scale;
14777  nk_size prog_value;
14778  struct nk_rect cursor;
14779 
14780  NK_ASSERT(style);
14781  NK_ASSERT(out);
14782  if (!out || !style) return 0;
14783 
14784  /* calculate progressbar cursor */
14785  cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
14786  cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
14787  cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
14788  prog_scale = (float)value / (float)max;
14789  cursor.w = (bounds.w - 2) * prog_scale;
14790 
14791  /* update progressbar */
14792  prog_value = NK_MIN(value, max);
14793  prog_value = nk_progress_behavior(state, in, bounds, max, prog_value, modifiable);
14794 
14795  /* draw progressbar */
14796  if (style->draw_begin) style->draw_begin(out, style->userdata);
14797  nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
14798  if (style->draw_end) style->draw_end(out, style->userdata);
14799  return prog_value;
14800 }
14801 
14802 /* ===============================================================
14803  *
14804  * SCROLLBAR
14805  *
14806  * ===============================================================*/
14807 NK_INTERN float
14808 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
14809  int has_scrolling, const struct nk_rect *scroll,
14810  const struct nk_rect *cursor, const struct nk_rect *empty0,
14811  const struct nk_rect *empty1, float scroll_offset,
14812  float target, float scroll_step, enum nk_orientation o)
14813 {
14814  nk_flags ws = 0;
14815  int left_mouse_down;
14816  int left_mouse_click_in_cursor;
14817  float scroll_delta;
14818 
14819  nk_widget_state_reset(state);
14820  if (!in) return scroll_offset;
14821 
14822  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
14823  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
14824  NK_BUTTON_LEFT, *cursor, nk_true);
14825  if (nk_input_is_mouse_hovering_rect(in, *scroll))
14826  *state = NK_WIDGET_STATE_HOVERED;
14827 
14828  scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
14829  if (left_mouse_down && left_mouse_click_in_cursor) {
14830  /* update cursor by mouse dragging */
14831  float pixel, delta;
14832  *state = NK_WIDGET_STATE_ACTIVE;
14833  if (o == NK_VERTICAL) {
14834  float cursor_y;
14835  pixel = in->mouse.delta.y;
14836  delta = (pixel / scroll->h) * target;
14837  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
14838  cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
14839  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
14840  } else {
14841  float cursor_x;
14842  pixel = in->mouse.delta.x;
14843  delta = (pixel / scroll->w) * target;
14844  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
14845  cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
14846  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
14847  }
14848  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
14849  nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
14850  /* scroll page up by click on empty space or shortcut */
14851  if (o == NK_VERTICAL)
14852  scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
14853  else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
14854  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
14855  nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
14856  /* scroll page down by click on empty space or shortcut */
14857  if (o == NK_VERTICAL)
14858  scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
14859  else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
14860  } else if (has_scrolling) {
14861  if ((scroll_delta < 0 || (scroll_delta > 0))) {
14862  /* update cursor by mouse scrolling */
14863  scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
14864  if (o == NK_VERTICAL)
14865  scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
14866  else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
14867  } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) {
14868  /* update cursor to the beginning */
14869  if (o == NK_VERTICAL) scroll_offset = 0;
14870  } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) {
14871  /* update cursor to the end */
14872  if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
14873  }
14874  }
14875  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
14876  *state |= NK_WIDGET_STATE_ENTERED;
14877  else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
14878  *state |= NK_WIDGET_STATE_LEFT;
14879  return scroll_offset;
14880 }
14881 
14882 NK_INTERN void
14883 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
14884  const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
14885  const struct nk_rect *scroll)
14886 {
14887  const struct nk_style_item *background;
14888  const struct nk_style_item *cursor;
14889 
14890  /* select correct colors/images to draw */
14891  if (state & NK_WIDGET_STATE_ACTIVED) {
14892  background = &style->active;
14893  cursor = &style->cursor_active;
14894  } else if (state & NK_WIDGET_STATE_HOVER) {
14895  background = &style->hover;
14896  cursor = &style->cursor_hover;
14897  } else {
14898  background = &style->normal;
14899  cursor = &style->cursor_normal;
14900  }
14901 
14902  /* draw background */
14903  if (background->type == NK_STYLE_ITEM_COLOR) {
14904  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14905  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14906  } else {
14907  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14908  }
14909 
14910  /* draw cursor */
14911  if (background->type == NK_STYLE_ITEM_COLOR) {
14912  nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
14913  nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
14914  } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
14915 }
14916 
14917 NK_INTERN float
14918 nk_do_scrollbarv(nk_flags *state,
14919  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
14920  float offset, float target, float step, float button_pixel_inc,
14921  const struct nk_style_scrollbar *style, struct nk_input *in,
14922  const struct nk_user_font *font)
14923 {
14924  struct nk_rect empty_north;
14925  struct nk_rect empty_south;
14926  struct nk_rect cursor;
14927 
14928  float scroll_step;
14929  float scroll_offset;
14930  float scroll_off;
14931  float scroll_ratio;
14932 
14933  NK_ASSERT(out);
14934  NK_ASSERT(style);
14935  NK_ASSERT(state);
14936  if (!out || !style) return 0;
14937 
14938  scroll.w = NK_MAX(scroll.w, 1);
14939  scroll.h = NK_MAX(scroll.h, 0);
14940  if (target <= scroll.h) return 0;
14941 
14942  /* optional scrollbar buttons */
14943  if (style->show_buttons) {
14944  nk_flags ws;
14945  float scroll_h;
14946  struct nk_rect button;
14947 
14948  button.x = scroll.x;
14949  button.w = scroll.w;
14950  button.h = scroll.w;
14951 
14952  scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
14953  scroll_step = NK_MIN(step, button_pixel_inc);
14954 
14955  /* decrement button */
14956  button.y = scroll.y;
14957  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
14958  NK_BUTTON_REPEATER, &style->dec_button, in, font))
14959  offset = offset - scroll_step;
14960 
14961  /* increment button */
14962  button.y = scroll.y + scroll.h - button.h;
14963  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
14964  NK_BUTTON_REPEATER, &style->inc_button, in, font))
14965  offset = offset + scroll_step;
14966 
14967  scroll.y = scroll.y + button.h;
14968  scroll.h = scroll_h;
14969  }
14970 
14971  /* calculate scrollbar constants */
14972  scroll_step = NK_MIN(step, scroll.h);
14973  scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
14974  scroll_ratio = scroll.h / target;
14975  scroll_off = scroll_offset / target;
14976 
14977  /* calculate scrollbar cursor bounds */
14978  cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
14979  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
14980  cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
14981  cursor.x = scroll.x + style->border + style->padding.x;
14982 
14983  /* calculate empty space around cursor */
14984  empty_north.x = scroll.x;
14985  empty_north.y = scroll.y;
14986  empty_north.w = scroll.w;
14987  empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
14988 
14989  empty_south.x = scroll.x;
14990  empty_south.y = cursor.y + cursor.h;
14991  empty_south.w = scroll.w;
14992  empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
14993 
14994  /* update scrollbar */
14995  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
14996  &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
14997  scroll_off = scroll_offset / target;
14998  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
14999 
15000  /* draw scrollbar */
15001  if (style->draw_begin) style->draw_begin(out, style->userdata);
15002  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
15003  if (style->draw_end) style->draw_end(out, style->userdata);
15004  return scroll_offset;
15005 }
15006 
15007 NK_INTERN float
15008 nk_do_scrollbarh(nk_flags *state,
15009  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
15010  float offset, float target, float step, float button_pixel_inc,
15011  const struct nk_style_scrollbar *style, struct nk_input *in,
15012  const struct nk_user_font *font)
15013 {
15014  struct nk_rect cursor;
15015  struct nk_rect empty_west;
15016  struct nk_rect empty_east;
15017 
15018  float scroll_step;
15019  float scroll_offset;
15020  float scroll_off;
15021  float scroll_ratio;
15022 
15023  NK_ASSERT(out);
15024  NK_ASSERT(style);
15025  if (!out || !style) return 0;
15026 
15027  /* scrollbar background */
15028  scroll.h = NK_MAX(scroll.h, 1);
15029  scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
15030  if (target <= scroll.w) return 0;
15031 
15032  /* optional scrollbar buttons */
15033  if (style->show_buttons) {
15034  nk_flags ws;
15035  float scroll_w;
15036  struct nk_rect button;
15037  button.y = scroll.y;
15038  button.w = scroll.h;
15039  button.h = scroll.h;
15040 
15041  scroll_w = scroll.w - 2 * button.w;
15042  scroll_step = NK_MIN(step, button_pixel_inc);
15043 
15044  /* decrement button */
15045  button.x = scroll.x;
15046  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
15047  NK_BUTTON_REPEATER, &style->dec_button, in, font))
15048  offset = offset - scroll_step;
15049 
15050  /* increment button */
15051  button.x = scroll.x + scroll.w - button.w;
15052  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
15053  NK_BUTTON_REPEATER, &style->inc_button, in, font))
15054  offset = offset + scroll_step;
15055 
15056  scroll.x = scroll.x + button.w;
15057  scroll.w = scroll_w;
15058  }
15059 
15060  /* calculate scrollbar constants */
15061  scroll_step = NK_MIN(step, scroll.w);
15062  scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
15063  scroll_ratio = scroll.w / target;
15064  scroll_off = scroll_offset / target;
15065 
15066  /* calculate cursor bounds */
15067  cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
15068  cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
15069  cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
15070  cursor.y = scroll.y + style->border + style->padding.y;
15071 
15072  /* calculate empty space around cursor */
15073  empty_west.x = scroll.x;
15074  empty_west.y = scroll.y;
15075  empty_west.w = cursor.x - scroll.x;
15076  empty_west.h = scroll.h;
15077 
15078  empty_east.x = cursor.x + cursor.w;
15079  empty_east.y = scroll.y;
15080  empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
15081  empty_east.h = scroll.h;
15082 
15083  /* update scrollbar */
15084  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
15085  &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
15086  scroll_off = scroll_offset / target;
15087  cursor.x = scroll.x + (scroll_off * scroll.w);
15088 
15089  /* draw scrollbar */
15090  if (style->draw_begin) style->draw_begin(out, style->userdata);
15091  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
15092  if (style->draw_end) style->draw_end(out, style->userdata);
15093  return scroll_offset;
15094 }
15095 
15096 /* ===============================================================
15097  *
15098  * FILTER
15099  *
15100  * ===============================================================*/
15101 NK_API int nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
15102 {(void)unicode;NK_UNUSED(box);return nk_true;}
15103 
15104 NK_API int
15105 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
15106 {
15107  NK_UNUSED(box);
15108  if (unicode > 128) return nk_false;
15109  else return nk_true;
15110 }
15111 
15112 NK_API int
15113 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
15114 {
15115  NK_UNUSED(box);
15116  if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
15117  return nk_false;
15118  else return nk_true;
15119 }
15120 
15121 NK_API int
15122 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
15123 {
15124  NK_UNUSED(box);
15125  if ((unicode < '0' || unicode > '9') && unicode != '-')
15126  return nk_false;
15127  else return nk_true;
15128 }
15129 
15130 NK_API int
15131 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
15132 {
15133  NK_UNUSED(box);
15134  if ((unicode < '0' || unicode > '9') &&
15135  (unicode < 'a' || unicode > 'f') &&
15136  (unicode < 'A' || unicode > 'F'))
15137  return nk_false;
15138  else return nk_true;
15139 }
15140 
15141 NK_API int
15142 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
15143 {
15144  NK_UNUSED(box);
15145  if (unicode < '0' || unicode > '7')
15146  return nk_false;
15147  else return nk_true;
15148 }
15149 
15150 NK_API int
15151 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
15152 {
15153  NK_UNUSED(box);
15154  if (unicode != '0' && unicode != '1')
15155  return nk_false;
15156  else return nk_true;
15157 }
15158 
15159 /* ===============================================================
15160  *
15161  * EDIT
15162  *
15163  * ===============================================================*/
15164 NK_INTERN void
15165 nk_edit_draw_text(struct nk_command_buffer *out,
15166  const struct nk_style_edit *style, float pos_x, float pos_y,
15167  float x_offset, const char *text, int byte_len, float row_height,
15168  const struct nk_user_font *font, struct nk_color background,
15169  struct nk_color foreground, int is_selected)
15170 {
15171  NK_ASSERT(out);
15172  NK_ASSERT(font);
15173  NK_ASSERT(style);
15174  if (!text || !byte_len || !out || !style) return;
15175 
15176  {int glyph_len = 0;
15177  nk_rune unicode = 0;
15178  int text_len = 0;
15179  float line_width = 0;
15180  float glyph_width;
15181  const char *line = text;
15182  float line_offset = 0;
15183  int line_count = 0;
15184 
15185  struct nk_text txt;
15186  txt.padding = nk_vec2(0,0);
15187  txt.background = background;
15188  txt.text = foreground;
15189 
15190  glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
15191  if (!glyph_len) return;
15192  while ((text_len < byte_len) && glyph_len)
15193  {
15194  if (unicode == '\n') {
15195  /* new line sepeator so draw previous line */
15196  struct nk_rect label;
15197  label.y = pos_y + line_offset;
15198  label.h = row_height;
15199  label.w = line_width;
15200  label.x = pos_x;
15201  if (!line_count)
15202  label.x += x_offset;
15203 
15204  if (is_selected) /* selection needs to draw different background color */
15205  nk_fill_rect(out, label, 0, background);
15206  nk_widget_text(out, label, line, (int)((text + text_len) - line),
15207  &txt, NK_TEXT_CENTERED, font);
15208 
15209  text_len++;
15210  line_count++;
15211  line_width = 0;
15212  line = text + text_len;
15213  line_offset += row_height;
15214  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
15215  continue;
15216  }
15217  if (unicode == '\r') {
15218  text_len++;
15219  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
15220  continue;
15221  }
15222  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
15223  line_width += (float)glyph_width;
15224  text_len += glyph_len;
15225  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
15226  continue;
15227  }
15228  if (line_width > 0) {
15229  /* draw last line */
15230  struct nk_rect label;
15231  label.y = pos_y + line_offset;
15232  label.h = row_height;
15233  label.w = line_width;
15234  label.x = pos_x;
15235  if (!line_count)
15236  label.x += x_offset;
15237 
15238  if (is_selected)
15239  nk_fill_rect(out, label, 0, background);
15240  nk_widget_text(out, label, line, (int)((text + text_len) - line),
15241  &txt, NK_TEXT_LEFT, font);
15242  }}
15243 }
15244 
15245 NK_INTERN nk_flags
15246 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
15247  struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
15248  struct nk_text_edit *edit, const struct nk_style_edit *style,
15249  struct nk_input *in, const struct nk_user_font *font)
15250 {
15251  struct nk_rect area;
15252  nk_flags ret = 0;
15253  float row_height;
15254  char prev_state = 0;
15255  char is_hovered = 0;
15256  char select_all = 0;
15257  char cursor_follow = 0;
15258  struct nk_rect old_clip;
15259  struct nk_rect clip;
15260 
15261  NK_ASSERT(state);
15262  NK_ASSERT(out);
15263  NK_ASSERT(style);
15264  if (!state || !out || !style)
15265  return ret;
15266 
15267  /* visible text area calculation */
15268  area.x = bounds.x + style->padding.x + style->border;
15269  area.y = bounds.y + style->padding.y + style->border;
15270  area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
15271  area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
15272  if (flags & NK_EDIT_MULTILINE)
15273  area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
15274  row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
15275 
15276  /* calculate clipping rectangle */
15277  old_clip = out->clip;
15278  nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
15279 
15280  /* update edit state */
15281  prev_state = (char)edit->active;
15282  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
15284  edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
15285  bounds.x, bounds.y, bounds.w, bounds.h);
15286  }
15287 
15288  /* (de)activate text editor */
15289  if (!prev_state && edit->active) {
15290  const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
15292  nk_textedit_clear_state(edit, type, filter);
15293  if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
15295  if (flags & NK_EDIT_AUTO_SELECT)
15296  select_all = nk_true;
15297  if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
15298  edit->cursor = edit->string.len;
15299  in = 0;
15300  }
15301  } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
15302  if (flags & NK_EDIT_READ_ONLY)
15303  edit->mode = NK_TEXT_EDIT_MODE_VIEW;
15304 
15305  ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
15306  if (prev_state != edit->active)
15307  ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
15308 
15309  /* handle user input */
15310  if (edit->active && in)
15311  {
15312  int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
15313  const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
15314  const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
15315 
15316  /* mouse click handler */
15317  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
15318  if (select_all) {
15319  nk_textedit_select_all(edit);
15320  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
15322  nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
15323  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
15324  (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
15325  nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
15326  cursor_follow = nk_true;
15327  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
15329  nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
15330  nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
15331  cursor_follow = nk_true;
15332  }
15333 
15334  {int i; /* keyboard input */
15335  int old_mode = edit->mode;
15336  for (i = 0; i < NK_KEY_MAX; ++i) {
15337  if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
15338  if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
15339  nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
15340  cursor_follow = nk_true;
15341  }
15342  }
15343  if (old_mode != edit->mode) {
15344  in->keyboard.text_len = 0;
15345  }}
15346 
15347  /* text input */
15348  edit->filter = filter;
15349  if (in->keyboard.text_len) {
15351  cursor_follow = nk_true;
15352  in->keyboard.text_len = 0;
15353  }
15354 
15355  /* enter key handler */
15357  cursor_follow = nk_true;
15358  if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
15359  nk_textedit_text(edit, "\n", 1);
15360  else if (flags & NK_EDIT_SIG_ENTER)
15361  ret |= NK_EDIT_COMMITED;
15362  else nk_textedit_text(edit, "\n", 1);
15363  }
15364 
15365  /* cut & copy handler */
15366  {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
15367  int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
15368  if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
15369  {
15370  int glyph_len;
15371  nk_rune unicode;
15372  const char *text;
15373  int b = edit->select_start;
15374  int e = edit->select_end;
15375 
15376  int begin = NK_MIN(b, e);
15377  int end = NK_MAX(b, e);
15378  text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
15379  if (edit->clip.copy)
15380  edit->clip.copy(edit->clip.userdata, text, end - begin);
15381  if (cut && !(flags & NK_EDIT_READ_ONLY)){
15382  nk_textedit_cut(edit);
15383  cursor_follow = nk_true;
15384  }
15385  }}
15386 
15387  /* paste handler */
15388  {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
15389  if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
15390  edit->clip.paste(edit->clip.userdata, edit);
15391  cursor_follow = nk_true;
15392  }}
15393 
15394  /* tab handler */
15395  {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
15396  if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
15397  nk_textedit_text(edit, " ", 4);
15398  cursor_follow = nk_true;
15399  }}
15400  }
15401 
15402  /* set widget state */
15403  if (edit->active)
15404  *state = NK_WIDGET_STATE_ACTIVE;
15405  else nk_widget_state_reset(state);
15406 
15407  if (is_hovered)
15408  *state |= NK_WIDGET_STATE_HOVERED;
15409 
15410  /* DRAW EDIT */
15411  {const char *text = nk_str_get_const(&edit->string);
15412  int len = nk_str_len_char(&edit->string);
15413 
15414  {/* select background colors/images */
15415  const struct nk_style_item *background;
15416  if (*state & NK_WIDGET_STATE_ACTIVED)
15417  background = &style->active;
15418  else if (*state & NK_WIDGET_STATE_HOVER)
15419  background = &style->hover;
15420  else background = &style->normal;
15421 
15422  /* draw background frame */
15423  if (background->type == NK_STYLE_ITEM_COLOR) {
15424  nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
15425  nk_fill_rect(out, bounds, style->rounding, background->data.color);
15426  } else nk_draw_image(out, bounds, &background->data.image, nk_white);}
15427 
15428  area.w = NK_MAX(0, area.w - style->cursor_size);
15429  if (edit->active)
15430  {
15431  int total_lines = 1;
15432  struct nk_vec2 text_size = nk_vec2(0,0);
15433 
15434  /* text pointer positions */
15435  const char *cursor_ptr = 0;
15436  const char *select_begin_ptr = 0;
15437  const char *select_end_ptr = 0;
15438 
15439  /* 2D pixel positions */
15440  struct nk_vec2 cursor_pos = nk_vec2(0,0);
15441  struct nk_vec2 selection_offset_start = nk_vec2(0,0);
15442  struct nk_vec2 selection_offset_end = nk_vec2(0,0);
15443 
15444  int selection_begin = NK_MIN(edit->select_start, edit->select_end);
15445  int selection_end = NK_MAX(edit->select_start, edit->select_end);
15446 
15447  /* calculate total line count + total space + cursor/selection position */
15448  float line_width = 0.0f;
15449  if (text && len)
15450  {
15451  /* utf8 encoding */
15452  float glyph_width;
15453  int glyph_len = 0;
15454  nk_rune unicode = 0;
15455  int text_len = 0;
15456  int glyphs = 0;
15457  int row_begin = 0;
15458 
15459  glyph_len = nk_utf_decode(text, &unicode, len);
15460  glyph_width = font->width(font->userdata, font->height, text, glyph_len);
15461  line_width = 0;
15462 
15463  /* iterate all lines */
15464  while ((text_len < len) && glyph_len)
15465  {
15466  /* set cursor 2D position and line */
15467  if (!cursor_ptr && glyphs == edit->cursor)
15468  {
15469  int glyph_offset;
15470  struct nk_vec2 out_offset;
15471  struct nk_vec2 row_size;
15472  const char *remaining;
15473 
15474  /* calculate 2d position */
15475  cursor_pos.y = (float)(total_lines-1) * row_height;
15476  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15477  text_len-row_begin, row_height, &remaining,
15478  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15479  cursor_pos.x = row_size.x;
15480  cursor_ptr = text + text_len;
15481  }
15482 
15483  /* set start selection 2D position and line */
15484  if (!select_begin_ptr && edit->select_start != edit->select_end &&
15485  glyphs == selection_begin)
15486  {
15487  int glyph_offset;
15488  struct nk_vec2 out_offset;
15489  struct nk_vec2 row_size;
15490  const char *remaining;
15491 
15492  /* calculate 2d position */
15493  selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
15494  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15495  text_len-row_begin, row_height, &remaining,
15496  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15497  selection_offset_start.x = row_size.x;
15498  select_begin_ptr = text + text_len;
15499  }
15500 
15501  /* set end selection 2D position and line */
15502  if (!select_end_ptr && edit->select_start != edit->select_end &&
15503  glyphs == selection_end)
15504  {
15505  int glyph_offset;
15506  struct nk_vec2 out_offset;
15507  struct nk_vec2 row_size;
15508  const char *remaining;
15509 
15510  /* calculate 2d position */
15511  selection_offset_end.y = (float)(total_lines-1) * row_height;
15512  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15513  text_len-row_begin, row_height, &remaining,
15514  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15515  selection_offset_end.x = row_size.x;
15516  select_end_ptr = text + text_len;
15517  }
15518  if (unicode == '\n') {
15519  text_size.x = NK_MAX(text_size.x, line_width);
15520  total_lines++;
15521  line_width = 0;
15522  text_len++;
15523  glyphs++;
15524  row_begin = text_len;
15525  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
15526  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
15527  continue;
15528  }
15529 
15530  glyphs++;
15531  text_len += glyph_len;
15532  line_width += (float)glyph_width;
15533 
15534  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
15535  glyph_width = font->width(font->userdata, font->height,
15536  text+text_len, glyph_len);
15537  continue;
15538  }
15539  text_size.y = (float)total_lines * row_height;
15540 
15541  /* handle case when cursor is at end of text buffer */
15542  if (!cursor_ptr && edit->cursor == edit->string.len) {
15543  cursor_pos.x = line_width;
15544  cursor_pos.y = text_size.y - row_height;
15545  }
15546  }
15547  {
15548  /* scrollbar */
15549  if (cursor_follow)
15550  {
15551  /* update scrollbar to follow cursor */
15552  if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
15553  /* horizontal scroll */
15554  const float scroll_increment = area.w * 0.25f;
15555  if (cursor_pos.x < edit->scrollbar.x)
15556  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
15557  if (cursor_pos.x >= edit->scrollbar.x + area.w)
15558  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x);
15559  } else edit->scrollbar.x = 0;
15560 
15561  if (flags & NK_EDIT_MULTILINE) {
15562  /* vertical scroll */
15563  if (cursor_pos.y < edit->scrollbar.y)
15564  edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
15565  if (cursor_pos.y >= edit->scrollbar.y + area.h)
15566  edit->scrollbar.y = edit->scrollbar.y + row_height;
15567  } else edit->scrollbar.y = 0;
15568  }
15569 
15570  /* scrollbar widget */
15571  if (flags & NK_EDIT_MULTILINE)
15572  {
15573  nk_flags ws;
15574  struct nk_rect scroll;
15575  float scroll_target;
15576  float scroll_offset;
15577  float scroll_step;
15578  float scroll_inc;
15579 
15580  scroll = area;
15581  scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
15582  scroll.w = style->scrollbar_size.x;
15583 
15584  scroll_offset = edit->scrollbar.y;
15585  scroll_step = scroll.h * 0.10f;
15586  scroll_inc = scroll.h * 0.01f;
15587  scroll_target = text_size.y;
15588  edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
15589  scroll_offset, scroll_target, scroll_step, scroll_inc,
15590  &style->scrollbar, in, font);
15591  }
15592  }
15593 
15594  /* draw text */
15595  {struct nk_color background_color;
15596  struct nk_color text_color;
15597  struct nk_color sel_background_color;
15598  struct nk_color sel_text_color;
15599  struct nk_color cursor_color;
15600  struct nk_color cursor_text_color;
15601  const struct nk_style_item *background;
15602  nk_push_scissor(out, clip);
15603 
15604  /* select correct colors to draw */
15605  if (*state & NK_WIDGET_STATE_ACTIVED) {
15606  background = &style->active;
15607  text_color = style->text_active;
15608  sel_text_color = style->selected_text_hover;
15609  sel_background_color = style->selected_hover;
15610  cursor_color = style->cursor_hover;
15611  cursor_text_color = style->cursor_text_hover;
15612  } else if (*state & NK_WIDGET_STATE_HOVER) {
15613  background = &style->hover;
15614  text_color = style->text_hover;
15615  sel_text_color = style->selected_text_hover;
15616  sel_background_color = style->selected_hover;
15617  cursor_text_color = style->cursor_text_hover;
15618  cursor_color = style->cursor_hover;
15619  } else {
15620  background = &style->normal;
15621  text_color = style->text_normal;
15622  sel_text_color = style->selected_text_normal;
15623  sel_background_color = style->selected_normal;
15624  cursor_color = style->cursor_normal;
15625  cursor_text_color = style->cursor_text_normal;
15626  }
15627  if (background->type == NK_STYLE_ITEM_IMAGE)
15628  background_color = nk_rgba(0,0,0,0);
15629  else background_color = background->data.color;
15630 
15631 
15632  if (edit->select_start == edit->select_end) {
15633  /* no selection so just draw the complete text */
15634  const char *begin = nk_str_get_const(&edit->string);
15635  int l = nk_str_len_char(&edit->string);
15636  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15637  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
15638  background_color, text_color, nk_false);
15639  } else {
15640  /* edit has selection so draw 1-3 text chunks */
15641  if (edit->select_start != edit->select_end && selection_begin > 0){
15642  /* draw unselected text before selection */
15643  const char *begin = nk_str_get_const(&edit->string);
15644  NK_ASSERT(select_begin_ptr);
15645  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15646  area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
15647  row_height, font, background_color, text_color, nk_false);
15648  }
15649  if (edit->select_start != edit->select_end) {
15650  /* draw selected text */
15651  NK_ASSERT(select_begin_ptr);
15652  if (!select_end_ptr) {
15653  const char *begin = nk_str_get_const(&edit->string);
15654  select_end_ptr = begin + nk_str_len_char(&edit->string);
15655  }
15656  nk_edit_draw_text(out, style,
15657  area.x - edit->scrollbar.x,
15658  area.y + selection_offset_start.y - edit->scrollbar.y,
15659  selection_offset_start.x,
15660  select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
15661  row_height, font, sel_background_color, sel_text_color, nk_true);
15662  }
15663  if ((edit->select_start != edit->select_end &&
15664  selection_end < edit->string.len))
15665  {
15666  /* draw unselected text after selected text */
15667  const char *begin = select_end_ptr;
15668  const char *end = nk_str_get_const(&edit->string) +
15669  nk_str_len_char(&edit->string);
15670  NK_ASSERT(select_end_ptr);
15671  nk_edit_draw_text(out, style,
15672  area.x - edit->scrollbar.x,
15673  area.y + selection_offset_end.y - edit->scrollbar.y,
15674  selection_offset_end.x,
15675  begin, (int)(end - begin), row_height, font,
15676  background_color, text_color, nk_true);
15677  }
15678  }
15679 
15680  /* cursor */
15681  if (edit->select_start == edit->select_end)
15682  {
15683  if (edit->cursor >= nk_str_len(&edit->string) ||
15684  (cursor_ptr && *cursor_ptr == '\n')) {
15685  /* draw cursor at end of line */
15686  struct nk_rect cursor;
15687  cursor.w = style->cursor_size;
15688  cursor.h = font->height;
15689  cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
15690  cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
15691  cursor.y -= edit->scrollbar.y;
15692  nk_fill_rect(out, cursor, 0, cursor_color);
15693  } else {
15694  /* draw cursor inside text */
15695  int glyph_len;
15696  struct nk_rect label;
15697  struct nk_text txt;
15698 
15699  nk_rune unicode;
15700  NK_ASSERT(cursor_ptr);
15701  glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
15702 
15703  label.x = area.x + cursor_pos.x - edit->scrollbar.x;
15704  label.y = area.y + cursor_pos.y - edit->scrollbar.y;
15705  label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
15706  label.h = row_height;
15707 
15708  txt.padding = nk_vec2(0,0);
15709  txt.background = cursor_color;;
15710  txt.text = cursor_text_color;
15711  nk_fill_rect(out, label, 0, cursor_color);
15712  nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
15713  }
15714  }}
15715  } else {
15716  /* not active so just draw text */
15717  int l = nk_str_len_char(&edit->string);
15718  const char *begin = nk_str_get_const(&edit->string);
15719 
15720  const struct nk_style_item *background;
15721  struct nk_color background_color;
15722  struct nk_color text_color;
15723  nk_push_scissor(out, clip);
15724  if (*state & NK_WIDGET_STATE_ACTIVED) {
15725  background = &style->active;
15726  text_color = style->text_active;
15727  } else if (*state & NK_WIDGET_STATE_HOVER) {
15728  background = &style->hover;
15729  text_color = style->text_hover;
15730  } else {
15731  background = &style->normal;
15732  text_color = style->text_normal;
15733  }
15734  if (background->type == NK_STYLE_ITEM_IMAGE)
15735  background_color = nk_rgba(0,0,0,0);
15736  else background_color = background->data.color;
15737  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15738  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
15739  background_color, text_color, nk_false);
15740  }
15741  nk_push_scissor(out, old_clip);}
15742  return ret;
15743 }
15744 
15745 /* ===============================================================
15746  *
15747  * PROPERTY
15748  *
15749  * ===============================================================*/
15750 enum nk_property_status {
15751  NK_PROPERTY_DEFAULT,
15752  NK_PROPERTY_EDIT,
15753  NK_PROPERTY_DRAG
15754 };
15755 enum nk_property_filter {
15756  NK_FILTER_INT,
15757  NK_FILTER_FLOAT
15758 };
15759 enum nk_property_kind {
15760  NK_PROPERTY_INT,
15761  NK_PROPERTY_FLOAT,
15762  NK_PROPERTY_DOUBLE
15763 };
15764 union nk_property {
15765  int i;
15766  float f;
15767  double d;
15768 };
15769 struct nk_property_variant {
15770  enum nk_property_kind kind;
15771  union nk_property value;
15772  union nk_property min_value;
15773  union nk_property max_value;
15774  union nk_property step;
15775 };
15776 
15777 NK_INTERN void
15778 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
15779  struct nk_rect drag, struct nk_property_variant *variant,
15780  float inc_per_pixel)
15781 {
15782  int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
15783  int left_mouse_click_in_cursor = in &&
15785 
15786  nk_widget_state_reset(state);
15787  if (nk_input_is_mouse_hovering_rect(in, drag))
15788  *state = NK_WIDGET_STATE_HOVERED;
15789 
15790  if (left_mouse_down && left_mouse_click_in_cursor) {
15791  float delta, pixels;
15792  pixels = in->mouse.delta.x;
15793  delta = pixels * inc_per_pixel;
15794  switch (variant->kind) {
15795  default: break;
15796  case NK_PROPERTY_INT:
15797  variant->value.i = variant->value.i + (int)delta;
15798  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
15799  break;
15800  case NK_PROPERTY_FLOAT:
15801  variant->value.f = variant->value.f + (float)delta;
15802  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
15803  break;
15804  case NK_PROPERTY_DOUBLE:
15805  variant->value.d = variant->value.d + (double)delta;
15806  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
15807  break;
15808  }
15809  *state = NK_WIDGET_STATE_ACTIVE;
15810  }
15811  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
15812  *state |= NK_WIDGET_STATE_ENTERED;
15813  else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
15814  *state |= NK_WIDGET_STATE_LEFT;
15815 }
15816 
15817 NK_INTERN void
15818 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
15819  struct nk_rect property, struct nk_rect label, struct nk_rect edit,
15820  struct nk_rect empty, int *state, struct nk_property_variant *variant,
15821  float inc_per_pixel)
15822 {
15823  if (in && *state == NK_PROPERTY_DEFAULT) {
15824  if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
15825  *state = NK_PROPERTY_EDIT;
15827  *state = NK_PROPERTY_DRAG;
15829  *state = NK_PROPERTY_DRAG;
15830  }
15831  if (*state == NK_PROPERTY_DRAG) {
15832  nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
15833  if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
15834  }
15835 }
15836 
15837 NK_INTERN void
15838 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
15839  const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
15840  const char *name, int len, const struct nk_user_font *font)
15841 {
15842  struct nk_text text;
15843  const struct nk_style_item *background;
15844 
15845  /* select correct background and text color */
15846  if (state & NK_WIDGET_STATE_ACTIVED) {
15847  background = &style->active;
15848  text.text = style->label_active;
15849  } else if (state & NK_WIDGET_STATE_HOVER) {
15850  background = &style->hover;
15851  text.text = style->label_hover;
15852  } else {
15853  background = &style->normal;
15854  text.text = style->label_normal;
15855  }
15856 
15857  /* draw background */
15858  if (background->type == NK_STYLE_ITEM_IMAGE) {
15859  nk_draw_image(out, *bounds, &background->data.image, nk_white);
15860  text.background = nk_rgba(0,0,0,0);
15861  } else {
15862  text.background = background->data.color;
15863  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
15864  nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
15865  }
15866 
15867  /* draw label */
15868  text.padding = nk_vec2(0,0);
15869  nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
15870 }
15871 
15872 NK_INTERN void
15873 nk_do_property(nk_flags *ws,
15874  struct nk_command_buffer *out, struct nk_rect property,
15875  const char *name, struct nk_property_variant *variant,
15876  float inc_per_pixel, char *buffer, int *len,
15877  int *state, int *cursor, int *select_begin, int *select_end,
15878  const struct nk_style_property *style,
15879  enum nk_property_filter filter, struct nk_input *in,
15880  const struct nk_user_font *font, struct nk_text_edit *text_edit,
15881  enum nk_button_behavior behavior)
15882 {
15883  const nk_plugin_filter filters[] = {
15886  };
15887  int active, old;
15888  int num_len, name_len;
15889  char string[NK_MAX_NUMBER_BUFFER];
15890  float size;
15891 
15892  char *dst = 0;
15893  int *length;
15894 
15895  struct nk_rect left;
15896  struct nk_rect right;
15897  struct nk_rect label;
15898  struct nk_rect edit;
15899  struct nk_rect empty;
15900 
15901  /* left decrement button */
15902  left.h = font->height/2;
15903  left.w = left.h;
15904  left.x = property.x + style->border + style->padding.x;
15905  left.y = property.y + style->border + property.h/2.0f - left.h/2;
15906 
15907  /* text label */
15908  name_len = nk_strlen(name);
15909  size = font->width(font->userdata, font->height, name, name_len);
15910  label.x = left.x + left.w + style->padding.x;
15911  label.w = (float)size + 2 * style->padding.x;
15912  label.y = property.y + style->border + style->padding.y;
15913  label.h = property.h - (2 * style->border + 2 * style->padding.y);
15914 
15915  /* right increment button */
15916  right.y = left.y;
15917  right.w = left.w;
15918  right.h = left.h;
15919  right.x = property.x + property.w - (right.w + style->padding.x);
15920 
15921  /* edit */
15922  if (*state == NK_PROPERTY_EDIT) {
15923  size = font->width(font->userdata, font->height, buffer, *len);
15924  size += style->edit.cursor_size;
15925  length = len;
15926  dst = buffer;
15927  } else {
15928  switch (variant->kind) {
15929  default: break;
15930  case NK_PROPERTY_INT:
15931  nk_itoa(string, variant->value.i);
15932  num_len = nk_strlen(string);
15933  break;
15934  case NK_PROPERTY_FLOAT:
15935  nk_dtoa(string, (double)variant->value.f);
15936  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
15937  break;
15938  case NK_PROPERTY_DOUBLE:
15939  nk_dtoa(string, variant->value.d);
15940  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
15941  break;
15942  }
15943  size = font->width(font->userdata, font->height, string, num_len);
15944  dst = string;
15945  length = &num_len;
15946  }
15947 
15948  edit.w = (float)size + 2 * style->padding.x;
15949  edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
15950  edit.x = right.x - (edit.w + style->padding.x);
15951  edit.y = property.y + style->border;
15952  edit.h = property.h - (2 * style->border);
15953 
15954  /* empty left space activator */
15955  empty.w = edit.x - (label.x + label.w);
15956  empty.x = label.x + label.w;
15957  empty.y = property.y;
15958  empty.h = property.h;
15959 
15960  /* update property */
15961  old = (*state == NK_PROPERTY_EDIT);
15962  nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
15963 
15964  /* draw property */
15965  if (style->draw_begin) style->draw_begin(out, style->userdata);
15966  nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
15967  if (style->draw_end) style->draw_end(out, style->userdata);
15968 
15969  /* execute right button */
15970  if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
15971  switch (variant->kind) {
15972  default: break;
15973  case NK_PROPERTY_INT:
15974  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
15975  case NK_PROPERTY_FLOAT:
15976  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
15977  case NK_PROPERTY_DOUBLE:
15978  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
15979  }
15980  }
15981 
15982  /* execute left button */
15983  if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
15984  switch (variant->kind) {
15985  default: break;
15986  case NK_PROPERTY_INT:
15987  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
15988  case NK_PROPERTY_FLOAT:
15989  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
15990  case NK_PROPERTY_DOUBLE:
15991  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
15992  }
15993  }
15994 
15995  if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
15996  /* property has been activated so setup buffer */
15997  NK_MEMCPY(buffer, dst, (nk_size)*length);
15998  *cursor = nk_utf_len(buffer, *length);
15999  *len = *length;
16000  length = len;
16001  dst = buffer;
16002  active = 0;
16003  } else active = (*state == NK_PROPERTY_EDIT);
16004 
16005  /* execute and run text edit field */
16006  nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
16007  text_edit->active = (unsigned char)active;
16008  text_edit->string.len = *length;
16009  text_edit->cursor = NK_CLAMP(0, *cursor, *length);
16010  text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
16011  text_edit->select_end = NK_CLAMP(0,*select_end, *length);
16012  text_edit->string.buffer.allocated = (nk_size)*length;
16014  text_edit->string.buffer.memory.ptr = dst;
16015  text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
16016  text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
16017  nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
16018  filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
16019 
16020  *length = text_edit->string.len;
16021  active = text_edit->active;
16022  *cursor = text_edit->cursor;
16023  *select_begin = text_edit->select_start;
16024  *select_end = text_edit->select_end;
16025 
16026  if (active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
16027  active = !active;
16028 
16029  if (old && !active) {
16030  /* property is now not active so convert edit text to value*/
16031  *state = NK_PROPERTY_DEFAULT;
16032  buffer[*len] = '\0';
16033  switch (variant->kind) {
16034  default: break;
16035  case NK_PROPERTY_INT:
16036  variant->value.i = nk_strtoi(buffer, 0);
16037  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
16038  break;
16039  case NK_PROPERTY_FLOAT:
16040  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
16041  variant->value.f = nk_strtof(buffer, 0);
16042  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
16043  break;
16044  case NK_PROPERTY_DOUBLE:
16045  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
16046  variant->value.d = nk_strtod(buffer, 0);
16047  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
16048  break;
16049  }
16050  }
16051 }
16052 /* ===============================================================
16053  *
16054  * COLOR PICKER
16055  *
16056  * ===============================================================*/
16057 NK_INTERN int
16058 nk_color_picker_behavior(nk_flags *state,
16059  const struct nk_rect *bounds, const struct nk_rect *matrix,
16060  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
16061  struct nk_color *color, const struct nk_input *in)
16062 {
16063  float hsva[4];
16064  int value_changed = 0;
16065  int hsv_changed = 0;
16066 
16067  NK_ASSERT(state);
16068  NK_ASSERT(matrix);
16069  NK_ASSERT(hue_bar);
16070  NK_ASSERT(color);
16071 
16072  /* color matrix */
16073  nk_color_hsva_fv(hsva, *color);
16074  if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
16075  hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
16076  hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
16077  value_changed = hsv_changed = 1;
16078  }
16079 
16080  /* hue bar */
16081  if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
16082  hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
16083  value_changed = hsv_changed = 1;
16084  }
16085 
16086  /* alpha bar */
16087  if (alpha_bar) {
16088  if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
16089  hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
16090  value_changed = 1;
16091  }
16092  }
16093  nk_widget_state_reset(state);
16094  if (hsv_changed) {
16095  *color = nk_hsva_fv(hsva);
16096  *state = NK_WIDGET_STATE_ACTIVE;
16097  }
16098  if (value_changed) {
16099  color->a = (nk_byte)(hsva[3] * 255.0f);
16100  *state = NK_WIDGET_STATE_ACTIVE;
16101  }
16102 
16103  /* set color picker widget state */
16104  if (nk_input_is_mouse_hovering_rect(in, *bounds))
16105  *state = NK_WIDGET_STATE_HOVERED;
16106  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
16107  *state |= NK_WIDGET_STATE_ENTERED;
16108  else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
16109  *state |= NK_WIDGET_STATE_LEFT;
16110  return value_changed;
16111 }
16112 
16113 NK_INTERN void
16114 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
16115  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
16116  struct nk_color color)
16117 {
16118  NK_STORAGE const struct nk_color black = {0,0,0,255};
16119  NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
16120  NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
16121 
16122  const float crosshair_size = 7.0f;
16123  struct nk_color temp;
16124  float hsva[4];
16125  float line_y;
16126  int i;
16127 
16128  NK_ASSERT(o);
16129  NK_ASSERT(matrix);
16130  NK_ASSERT(hue_bar);
16131 
16132  /* draw hue bar */
16133  nk_color_hsv_fv(hsva, color);
16134  for (i = 0; i < 6; ++i) {
16135  NK_GLOBAL const struct nk_color hue_colors[] = {
16136  {255, 0, 0, 255},
16137  {255,255,0,255},
16138  {0,255,0,255},
16139  {0, 255,255,255},
16140  {0,0,255,255},
16141  {255, 0, 255, 255},
16142  {255, 0, 0, 255}
16143  };
16145  nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
16146  hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
16147  hue_colors[i+1], hue_colors[i+1]);
16148  }
16149  line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
16150  nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
16151  line_y, 1, nk_rgb(255,255,255));
16152 
16153  /* draw alpha bar */
16154  if (alpha_bar) {
16155  float alpha = NK_SATURATE((float)color.a/255.0f);
16156  line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f);
16157 
16158  nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
16159  nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
16160  line_y, 1, nk_rgb(255,255,255));
16161  }
16162 
16163  /* draw color matrix */
16164  temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
16165  nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
16166  nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
16167 
16168  /* draw cross-hair */
16169  {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
16170  p.x = (float)(int)(matrix->x + S * matrix->w);
16171  p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
16172  nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
16173  nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
16174  nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
16175  nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
16176 }
16177 
16178 NK_INTERN int
16179 nk_do_color_picker(nk_flags *state,
16180  struct nk_command_buffer *out, struct nk_color *color,
16181  enum nk_color_format fmt, struct nk_rect bounds,
16182  struct nk_vec2 padding, const struct nk_input *in,
16183  const struct nk_user_font *font)
16184 {
16185  int ret = 0;
16186  struct nk_rect matrix;
16187  struct nk_rect hue_bar;
16188  struct nk_rect alpha_bar;
16189  float bar_w;
16190 
16191  NK_ASSERT(out);
16192  NK_ASSERT(color);
16193  NK_ASSERT(state);
16194  NK_ASSERT(font);
16195  if (!out || !color || !state || !font)
16196  return ret;
16197 
16198  bar_w = font->height;
16199  bounds.x += padding.x;
16200  bounds.y += padding.x;
16201  bounds.w -= 2 * padding.x;
16202  bounds.h -= 2 * padding.y;
16203 
16204  matrix.x = bounds.x;
16205  matrix.y = bounds.y;
16206  matrix.h = bounds.h;
16207  matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
16208 
16209  hue_bar.w = bar_w;
16210  hue_bar.y = bounds.y;
16211  hue_bar.h = matrix.h;
16212  hue_bar.x = matrix.x + matrix.w + padding.x;
16213 
16214  alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
16215  alpha_bar.y = bounds.y;
16216  alpha_bar.w = bar_w;
16217  alpha_bar.h = matrix.h;
16218 
16219  ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
16220  (fmt == NK_RGBA) ? &alpha_bar:0, color, in);
16221  nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *color);
16222  return ret;
16223 }
16224 
16225 /* ==============================================================
16226  *
16227  * STYLE
16228  *
16229  * ===============================================================*/
16230 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
16231 #define NK_COLOR_MAP(NK_COLOR)\
16232  NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \
16233  NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \
16234  NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \
16235  NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \
16236  NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \
16237  NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \
16238  NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \
16239  NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \
16240  NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \
16241  NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \
16242  NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \
16243  NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \
16244  NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \
16245  NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \
16246  NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \
16247  NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \
16248  NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \
16249  NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \
16250  NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \
16251  NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \
16252  NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \
16253  NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \
16254  NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,255, 0, 0, 255) \
16255  NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \
16256  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \
16257  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,120,120,120,255) \
16258  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,150,150,150,255) \
16259  NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255)
16260 
16261 NK_GLOBAL const struct nk_color
16262 nk_default_color_style[NK_COLOR_COUNT] = {
16263 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
16264  NK_COLOR_MAP(NK_COLOR)
16265 #undef NK_COLOR
16266 };
16267 
16268 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
16269 #define NK_COLOR(a,b,c,d,e) #a,
16270  NK_COLOR_MAP(NK_COLOR)
16271 #undef NK_COLOR
16272 };
16273 
16275 {return nk_color_names[c];}
16276 
16278 {struct nk_style_item i; i.type = NK_STYLE_ITEM_IMAGE; i.data.image = img; return i;}
16279 
16281 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = col; return i;}
16282 
16284 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = nk_rgba(0,0,0,0); return i;}
16285 
16286 NK_API void
16287 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
16288 {
16289  struct nk_style *style;
16290  struct nk_style_text *text;
16291  struct nk_style_button *button;
16292  struct nk_style_toggle *toggle;
16293  struct nk_style_selectable *select;
16294  struct nk_style_slider *slider;
16295  struct nk_style_progress *prog;
16296  struct nk_style_scrollbar *scroll;
16297  struct nk_style_edit *edit;
16298  struct nk_style_property *property;
16299  struct nk_style_combo *combo;
16300  struct nk_style_chart *chart;
16301  struct nk_style_tab *tab;
16302  struct nk_style_window *win;
16303 
16304  NK_ASSERT(ctx);
16305  if (!ctx) return;
16306  style = &ctx->style;
16307  table = (!table) ? nk_default_color_style: table;
16308 
16309  /* default text */
16310  text = &style->text;
16311  text->color = table[NK_COLOR_TEXT];
16312  text->padding = nk_vec2(0,0);
16313 
16314  /* default button */
16315  button = &style->button;
16316  nk_zero_struct(*button);
16317  button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]);
16320  button->border_color = table[NK_COLOR_BORDER];
16321  button->text_background = table[NK_COLOR_BUTTON];
16322  button->text_normal = table[NK_COLOR_TEXT];
16323  button->text_hover = table[NK_COLOR_TEXT];
16324  button->text_active = table[NK_COLOR_TEXT];
16325  button->padding = nk_vec2(2.0f,2.0f);
16326  button->image_padding = nk_vec2(0.0f,0.0f);
16327  button->touch_padding = nk_vec2(0.0f, 0.0f);
16328  button->userdata = nk_handle_ptr(0);
16329  button->text_alignment = NK_TEXT_CENTERED;
16330  button->border = 1.0f;
16331  button->rounding = 4.0f;
16332  button->draw_begin = 0;
16333  button->draw_end = 0;
16334 
16335  /* contextual button */
16336  button = &style->contextual_button;
16337  nk_zero_struct(*button);
16338  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
16341  button->border_color = table[NK_COLOR_WINDOW];
16342  button->text_background = table[NK_COLOR_WINDOW];
16343  button->text_normal = table[NK_COLOR_TEXT];
16344  button->text_hover = table[NK_COLOR_TEXT];
16345  button->text_active = table[NK_COLOR_TEXT];
16346  button->padding = nk_vec2(2.0f,2.0f);
16347  button->touch_padding = nk_vec2(0.0f,0.0f);
16348  button->userdata = nk_handle_ptr(0);
16349  button->text_alignment = NK_TEXT_CENTERED;
16350  button->border = 0.0f;
16351  button->rounding = 0.0f;
16352  button->draw_begin = 0;
16353  button->draw_end = 0;
16354 
16355  /* menu button */
16356  button = &style->menu_button;
16357  nk_zero_struct(*button);
16358  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
16359  button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
16360  button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
16361  button->border_color = table[NK_COLOR_WINDOW];
16362  button->text_background = table[NK_COLOR_WINDOW];
16363  button->text_normal = table[NK_COLOR_TEXT];
16364  button->text_hover = table[NK_COLOR_TEXT];
16365  button->text_active = table[NK_COLOR_TEXT];
16366  button->padding = nk_vec2(2.0f,2.0f);
16367  button->touch_padding = nk_vec2(0.0f,0.0f);
16368  button->userdata = nk_handle_ptr(0);
16369  button->text_alignment = NK_TEXT_CENTERED;
16370  button->border = 0.0f;
16371  button->rounding = 1.0f;
16372  button->draw_begin = 0;
16373  button->draw_end = 0;
16374 
16375  /* checkbox toggle */
16376  toggle = &style->checkbox;
16377  nk_zero_struct(*toggle);
16378  toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
16383  toggle->userdata = nk_handle_ptr(0);
16384  toggle->text_background = table[NK_COLOR_WINDOW];
16385  toggle->text_normal = table[NK_COLOR_TEXT];
16386  toggle->text_hover = table[NK_COLOR_TEXT];
16387  toggle->text_active = table[NK_COLOR_TEXT];
16388  toggle->padding = nk_vec2(2.0f, 2.0f);
16389  toggle->touch_padding = nk_vec2(0,0);
16390  toggle->border_color = nk_rgba(0,0,0,0);
16391  toggle->border = 0.0f;
16392  toggle->spacing = 4;
16393 
16394  /* option toggle */
16395  toggle = &style->option;
16396  nk_zero_struct(*toggle);
16397  toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
16402  toggle->userdata = nk_handle_ptr(0);
16403  toggle->text_background = table[NK_COLOR_WINDOW];
16404  toggle->text_normal = table[NK_COLOR_TEXT];
16405  toggle->text_hover = table[NK_COLOR_TEXT];
16406  toggle->text_active = table[NK_COLOR_TEXT];
16407  toggle->padding = nk_vec2(3.0f, 3.0f);
16408  toggle->touch_padding = nk_vec2(0,0);
16409  toggle->border_color = nk_rgba(0,0,0,0);
16410  toggle->border = 0.0f;
16411  toggle->spacing = 4;
16412 
16413  /* selectable */
16414  select = &style->selectable;
16415  nk_zero_struct(*select);
16416  select->normal = nk_style_item_color(table[NK_COLOR_SELECT]);
16417  select->hover = nk_style_item_color(table[NK_COLOR_SELECT]);
16418  select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]);
16422  select->text_normal = table[NK_COLOR_TEXT];
16423  select->text_hover = table[NK_COLOR_TEXT];
16424  select->text_pressed = table[NK_COLOR_TEXT];
16425  select->text_normal_active = table[NK_COLOR_TEXT];
16426  select->text_hover_active = table[NK_COLOR_TEXT];
16427  select->text_pressed_active = table[NK_COLOR_TEXT];
16428  select->padding = nk_vec2(2.0f,2.0f);
16429  select->touch_padding = nk_vec2(0,0);
16430  select->userdata = nk_handle_ptr(0);
16431  select->rounding = 0.0f;
16432  select->draw_begin = 0;
16433  select->draw_end = 0;
16434 
16435  /* slider */
16436  slider = &style->slider;
16437  nk_zero_struct(*slider);
16438  slider->normal = nk_style_item_hide();
16439  slider->hover = nk_style_item_hide();
16440  slider->active = nk_style_item_hide();
16441  slider->bar_normal = table[NK_COLOR_SLIDER];
16442  slider->bar_hover = table[NK_COLOR_SLIDER];
16443  slider->bar_active = table[NK_COLOR_SLIDER];
16444  slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR];
16450  slider->cursor_size = nk_vec2(16,16);
16451  slider->padding = nk_vec2(2,2);
16452  slider->spacing = nk_vec2(2,2);
16453  slider->userdata = nk_handle_ptr(0);
16454  slider->show_buttons = nk_false;
16455  slider->bar_height = 8;
16456  slider->rounding = 0;
16457  slider->draw_begin = 0;
16458  slider->draw_end = 0;
16459 
16460  /* slider buttons */
16461  button = &style->slider.inc_button;
16462  button->normal = nk_style_item_color(nk_rgb(40,40,40));
16463  button->hover = nk_style_item_color(nk_rgb(42,42,42));
16464  button->active = nk_style_item_color(nk_rgb(44,44,44));
16465  button->border_color = nk_rgb(65,65,65);
16466  button->text_background = nk_rgb(40,40,40);
16467  button->text_normal = nk_rgb(175,175,175);
16468  button->text_hover = nk_rgb(175,175,175);
16469  button->text_active = nk_rgb(175,175,175);
16470  button->padding = nk_vec2(8.0f,8.0f);
16471  button->touch_padding = nk_vec2(0.0f,0.0f);
16472  button->userdata = nk_handle_ptr(0);
16473  button->text_alignment = NK_TEXT_CENTERED;
16474  button->border = 1.0f;
16475  button->rounding = 0.0f;
16476  button->draw_begin = 0;
16477  button->draw_end = 0;
16478  style->slider.dec_button = style->slider.inc_button;
16479 
16480  /* progressbar */
16481  prog = &style->progress;
16482  nk_zero_struct(*prog);
16483  prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]);
16484  prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]);
16485  prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]);
16489  prog->border_color = nk_rgba(0,0,0,0);
16490  prog->cursor_border_color = nk_rgba(0,0,0,0);
16491  prog->userdata = nk_handle_ptr(0);
16492  prog->padding = nk_vec2(4,4);
16493  prog->rounding = 0;
16494  prog->border = 0;
16495  prog->cursor_rounding = 0;
16496  prog->cursor_border = 0;
16497  prog->draw_begin = 0;
16498  prog->draw_end = 0;
16499 
16500  /* scrollbars */
16501  scroll = &style->scrollh;
16502  nk_zero_struct(*scroll);
16503  scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16504  scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16505  scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16511  scroll->userdata = nk_handle_ptr(0);
16512  scroll->border_color = table[NK_COLOR_SCROLLBAR];
16513  scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
16514  scroll->padding = nk_vec2(0,0);
16515  scroll->show_buttons = nk_false;
16516  scroll->border = 0;
16517  scroll->rounding = 0;
16518  scroll->border_cursor = 0;
16519  scroll->rounding_cursor = 0;
16520  scroll->draw_begin = 0;
16521  scroll->draw_end = 0;
16522  style->scrollv = style->scrollh;
16523 
16524  /* scrollbars buttons */
16525  button = &style->scrollh.inc_button;
16526  button->normal = nk_style_item_color(nk_rgb(40,40,40));
16527  button->hover = nk_style_item_color(nk_rgb(42,42,42));
16528  button->active = nk_style_item_color(nk_rgb(44,44,44));
16529  button->border_color = nk_rgb(65,65,65);
16530  button->text_background = nk_rgb(40,40,40);
16531  button->text_normal = nk_rgb(175,175,175);
16532  button->text_hover = nk_rgb(175,175,175);
16533  button->text_active = nk_rgb(175,175,175);
16534  button->padding = nk_vec2(4.0f,4.0f);
16535  button->touch_padding = nk_vec2(0.0f,0.0f);
16536  button->userdata = nk_handle_ptr(0);
16537  button->text_alignment = NK_TEXT_CENTERED;
16538  button->border = 1.0f;
16539  button->rounding = 0.0f;
16540  button->draw_begin = 0;
16541  button->draw_end = 0;
16542  style->scrollh.dec_button = style->scrollh.inc_button;
16543  style->scrollv.inc_button = style->scrollh.inc_button;
16544  style->scrollv.dec_button = style->scrollh.inc_button;
16545 
16546  /* edit */
16547  edit = &style->edit;
16548  nk_zero_struct(*edit);
16549  edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]);
16550  edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]);
16551  edit->active = nk_style_item_color(table[NK_COLOR_EDIT]);
16552  edit->cursor_normal = table[NK_COLOR_TEXT];
16553  edit->cursor_hover = table[NK_COLOR_TEXT];
16554  edit->cursor_text_normal= table[NK_COLOR_EDIT];
16555  edit->cursor_text_hover = table[NK_COLOR_EDIT];
16556  edit->border_color = table[NK_COLOR_BORDER];
16557  edit->text_normal = table[NK_COLOR_TEXT];
16558  edit->text_hover = table[NK_COLOR_TEXT];
16559  edit->text_active = table[NK_COLOR_TEXT];
16560  edit->selected_normal = table[NK_COLOR_TEXT];
16561  edit->selected_hover = table[NK_COLOR_TEXT];
16562  edit->selected_text_normal = table[NK_COLOR_EDIT];
16563  edit->selected_text_hover = table[NK_COLOR_EDIT];
16564  edit->scrollbar_size = nk_vec2(10,10);
16565  edit->scrollbar = style->scrollv;
16566  edit->padding = nk_vec2(4,4);
16567  edit->row_padding = 2;
16568  edit->cursor_size = 4;
16569  edit->border = 1;
16570  edit->rounding = 0;
16571 
16572  /* property */
16573  property = &style->property;
16574  nk_zero_struct(*property);
16575  property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16576  property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16577  property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16578  property->border_color = table[NK_COLOR_BORDER];
16579  property->label_normal = table[NK_COLOR_TEXT];
16580  property->label_hover = table[NK_COLOR_TEXT];
16581  property->label_active = table[NK_COLOR_TEXT];
16582  property->sym_left = NK_SYMBOL_TRIANGLE_LEFT;
16583  property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT;
16584  property->userdata = nk_handle_ptr(0);
16585  property->padding = nk_vec2(4,4);
16586  property->border = 1;
16587  property->rounding = 10;
16588  property->draw_begin = 0;
16589  property->draw_end = 0;
16590 
16591  /* property buttons */
16592  button = &style->property.dec_button;
16593  nk_zero_struct(*button);
16594  button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16595  button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16596  button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16597  button->border_color = nk_rgba(0,0,0,0);
16598  button->text_background = table[NK_COLOR_PROPERTY];
16599  button->text_normal = table[NK_COLOR_TEXT];
16600  button->text_hover = table[NK_COLOR_TEXT];
16601  button->text_active = table[NK_COLOR_TEXT];
16602  button->padding = nk_vec2(0.0f,0.0f);
16603  button->touch_padding = nk_vec2(0.0f,0.0f);
16604  button->userdata = nk_handle_ptr(0);
16605  button->text_alignment = NK_TEXT_CENTERED;
16606  button->border = 0.0f;
16607  button->rounding = 0.0f;
16608  button->draw_begin = 0;
16609  button->draw_end = 0;
16610  style->property.inc_button = style->property.dec_button;
16611 
16612  /* property edit */
16613  edit = &style->property.edit;
16614  nk_zero_struct(*edit);
16618  edit->border_color = nk_rgba(0,0,0,0);
16619  edit->cursor_normal = table[NK_COLOR_TEXT];
16620  edit->cursor_hover = table[NK_COLOR_TEXT];
16621  edit->cursor_text_normal= table[NK_COLOR_EDIT];
16622  edit->cursor_text_hover = table[NK_COLOR_EDIT];
16623  edit->text_normal = table[NK_COLOR_TEXT];
16624  edit->text_hover = table[NK_COLOR_TEXT];
16625  edit->text_active = table[NK_COLOR_TEXT];
16626  edit->selected_normal = table[NK_COLOR_TEXT];
16627  edit->selected_hover = table[NK_COLOR_TEXT];
16628  edit->selected_text_normal = table[NK_COLOR_EDIT];
16629  edit->selected_text_hover = table[NK_COLOR_EDIT];
16630  edit->padding = nk_vec2(0,0);
16631  edit->cursor_size = 8;
16632  edit->border = 0;
16633  edit->rounding = 0;
16634 
16635  /* chart */
16636  chart = &style->chart;
16637  nk_zero_struct(*chart);
16639  chart->border_color = table[NK_COLOR_BORDER];
16641  chart->color = table[NK_COLOR_CHART_COLOR];
16642  chart->padding = nk_vec2(4,4);
16643  chart->border = 0;
16644  chart->rounding = 0;
16645 
16646  /* combo */
16647  combo = &style->combo;
16648  combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
16649  combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
16650  combo->active = nk_style_item_color(table[NK_COLOR_COMBO]);
16651  combo->border_color = table[NK_COLOR_BORDER];
16652  combo->label_normal = table[NK_COLOR_TEXT];
16653  combo->label_hover = table[NK_COLOR_TEXT];
16654  combo->label_active = table[NK_COLOR_TEXT];
16658  combo->content_padding = nk_vec2(4,4);
16659  combo->button_padding = nk_vec2(0,4);
16660  combo->spacing = nk_vec2(4,0);
16661  combo->border = 1;
16662  combo->rounding = 0;
16663 
16664  /* combo button */
16665  button = &style->combo.button;
16666  nk_zero_struct(*button);
16667  button->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
16668  button->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
16669  button->active = nk_style_item_color(table[NK_COLOR_COMBO]);
16670  button->border_color = nk_rgba(0,0,0,0);
16671  button->text_background = table[NK_COLOR_COMBO];
16672  button->text_normal = table[NK_COLOR_TEXT];
16673  button->text_hover = table[NK_COLOR_TEXT];
16674  button->text_active = table[NK_COLOR_TEXT];
16675  button->padding = nk_vec2(2.0f,2.0f);
16676  button->touch_padding = nk_vec2(0.0f,0.0f);
16677  button->userdata = nk_handle_ptr(0);
16678  button->text_alignment = NK_TEXT_CENTERED;
16679  button->border = 0.0f;
16680  button->rounding = 0.0f;
16681  button->draw_begin = 0;
16682  button->draw_end = 0;
16683 
16684  /* tab */
16685  tab = &style->tab;
16687  tab->border_color = table[NK_COLOR_BORDER];
16688  tab->text = table[NK_COLOR_TEXT];
16691  tab->padding = nk_vec2(4,4);
16692  tab->spacing = nk_vec2(4,4);
16693  tab->indent = 10.0f;
16694  tab->border = 1;
16695  tab->rounding = 0;
16696 
16697  /* tab button */
16698  button = &style->tab.tab_minimize_button;
16699  nk_zero_struct(*button);
16701  button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
16703  button->border_color = nk_rgba(0,0,0,0);
16704  button->text_background = table[NK_COLOR_TAB_HEADER];
16705  button->text_normal = table[NK_COLOR_TEXT];
16706  button->text_hover = table[NK_COLOR_TEXT];
16707  button->text_active = table[NK_COLOR_TEXT];
16708  button->padding = nk_vec2(2.0f,2.0f);
16709  button->touch_padding = nk_vec2(0.0f,0.0f);
16710  button->userdata = nk_handle_ptr(0);
16711  button->text_alignment = NK_TEXT_CENTERED;
16712  button->border = 0.0f;
16713  button->rounding = 0.0f;
16714  button->draw_begin = 0;
16715  button->draw_end = 0;
16716  style->tab.tab_maximize_button =*button;
16717 
16718  /* node button */
16719  button = &style->tab.node_minimize_button;
16720  nk_zero_struct(*button);
16721  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
16722  button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
16723  button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
16724  button->border_color = nk_rgba(0,0,0,0);
16725  button->text_background = table[NK_COLOR_TAB_HEADER];
16726  button->text_normal = table[NK_COLOR_TEXT];
16727  button->text_hover = table[NK_COLOR_TEXT];
16728  button->text_active = table[NK_COLOR_TEXT];
16729  button->padding = nk_vec2(2.0f,2.0f);
16730  button->touch_padding = nk_vec2(0.0f,0.0f);
16731  button->userdata = nk_handle_ptr(0);
16732  button->text_alignment = NK_TEXT_CENTERED;
16733  button->border = 0.0f;
16734  button->rounding = 0.0f;
16735  button->draw_begin = 0;
16736  button->draw_end = 0;
16737  style->tab.node_maximize_button =*button;
16738 
16739  /* window header */
16740  win = &style->window;
16741  win->header.align = NK_HEADER_RIGHT;
16748  win->header.label_normal = table[NK_COLOR_TEXT];
16749  win->header.label_hover = table[NK_COLOR_TEXT];
16750  win->header.label_active = table[NK_COLOR_TEXT];
16751  win->header.label_padding = nk_vec2(4,4);
16752  win->header.padding = nk_vec2(4,4);
16753  win->header.spacing = nk_vec2(0,0);
16754 
16755  /* window header close button */
16756  button = &style->window.header.close_button;
16757  nk_zero_struct(*button);
16758  button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
16759  button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
16760  button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
16761  button->border_color = nk_rgba(0,0,0,0);
16762  button->text_background = table[NK_COLOR_HEADER];
16763  button->text_normal = table[NK_COLOR_TEXT];
16764  button->text_hover = table[NK_COLOR_TEXT];
16765  button->text_active = table[NK_COLOR_TEXT];
16766  button->padding = nk_vec2(0.0f,0.0f);
16767  button->touch_padding = nk_vec2(0.0f,0.0f);
16768  button->userdata = nk_handle_ptr(0);
16769  button->text_alignment = NK_TEXT_CENTERED;
16770  button->border = 0.0f;
16771  button->rounding = 0.0f;
16772  button->draw_begin = 0;
16773  button->draw_end = 0;
16774 
16775  /* window header minimize button */
16776  button = &style->window.header.minimize_button;
16777  nk_zero_struct(*button);
16778  button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
16779  button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
16780  button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
16781  button->border_color = nk_rgba(0,0,0,0);
16782  button->text_background = table[NK_COLOR_HEADER];
16783  button->text_normal = table[NK_COLOR_TEXT];
16784  button->text_hover = table[NK_COLOR_TEXT];
16785  button->text_active = table[NK_COLOR_TEXT];
16786  button->padding = nk_vec2(0.0f,0.0f);
16787  button->touch_padding = nk_vec2(0.0f,0.0f);
16788  button->userdata = nk_handle_ptr(0);
16789  button->text_alignment = NK_TEXT_CENTERED;
16790  button->border = 0.0f;
16791  button->rounding = 0.0f;
16792  button->draw_begin = 0;
16793  button->draw_end = 0;
16794 
16795  /* window */
16796  win->background = table[NK_COLOR_WINDOW];
16798  win->border_color = table[NK_COLOR_BORDER];
16799  win->popup_border_color = table[NK_COLOR_BORDER];
16800  win->combo_border_color = table[NK_COLOR_BORDER];
16802  win->menu_border_color = table[NK_COLOR_BORDER];
16803  win->group_border_color = table[NK_COLOR_BORDER];
16804  win->tooltip_border_color = table[NK_COLOR_BORDER];
16805  win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]);
16806 
16807  win->rounding = 0.0f;
16808  win->spacing = nk_vec2(4,4);
16809  win->scrollbar_size = nk_vec2(10,10);
16810  win->min_size = nk_vec2(64,64);
16811 
16812  win->combo_border = 1.0f;
16813  win->contextual_border = 1.0f;
16814  win->menu_border = 1.0f;
16815  win->group_border = 1.0f;
16816  win->tooltip_border = 1.0f;
16817  win->popup_border = 1.0f;
16818  win->border = 2.0f;
16819 
16820  win->padding = nk_vec2(4,4);
16821  win->group_padding = nk_vec2(4,4);
16822  win->popup_padding = nk_vec2(4,4);
16823  win->combo_padding = nk_vec2(4,4);
16824  win->contextual_padding = nk_vec2(4,4);
16825  win->menu_padding = nk_vec2(4,4);
16826  win->tooltip_padding = nk_vec2(4,4);
16827 }
16828 
16829 NK_API void
16830 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
16831 {
16832  struct nk_style *style;
16833  NK_ASSERT(ctx);
16834  if (!ctx) return;
16835  style = &ctx->style;
16836  style->font = font;
16837  ctx->stacks.fonts.head = 0;
16838 }
16839 
16840 NK_API int
16841 nk_style_push_font(struct nk_context *ctx, struct nk_user_font *font)
16842 {
16843  struct nk_config_stack_user_font *font_stack;
16844  struct nk_config_stack_user_font_element *element;
16845 
16846  NK_ASSERT(ctx);
16847  if (!ctx) return 0;
16848 
16849  font_stack = &ctx->stacks.fonts;
16850  NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
16851  if (font_stack->head >= (int)NK_LEN(font_stack->elements))
16852  return 0;
16853 
16854  element = &font_stack->elements[font_stack->head++];
16855  element->address = &ctx->style.font;
16856  element->old_value = ctx->style.font;
16857  ctx->style.font = font;
16858  return 1;
16859 }
16860 
16861 NK_API int
16862 nk_style_pop_font(struct nk_context *ctx)
16863 {
16864  struct nk_config_stack_user_font *font_stack;
16865  struct nk_config_stack_user_font_element *element;
16866 
16867  NK_ASSERT(ctx);
16868  if (!ctx) return 0;
16869 
16870  font_stack = &ctx->stacks.fonts;
16871  NK_ASSERT(font_stack->head > 0);
16872  if (font_stack->head < 1)
16873  return 0;
16874 
16875  element = &font_stack->elements[--font_stack->head];
16876  *element->address = element->old_value;
16877  return 1;
16878 }
16879 
16880 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
16881 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
16882 {\
16883  struct nk_config_stack_##type * type_stack;\
16884  struct nk_config_stack_##type##_element *element;\
16885  NK_ASSERT(ctx);\
16886  if (!ctx) return 0;\
16887  type_stack = &ctx->stacks.stack;\
16888  NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
16889  if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
16890  return 0;\
16891  element = &type_stack->elements[type_stack->head++];\
16892  element->address = address;\
16893  element->old_value = *address;\
16894  *address = value;\
16895  return 1;\
16896 }
16897 
16898 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
16899 nk_style_pop_##type(struct nk_context *ctx)\
16900 {\
16901  struct nk_config_stack_##type *type_stack;\
16902  struct nk_config_stack_##type##_element *element;\
16903  NK_ASSERT(ctx);\
16904  if (!ctx) return 0;\
16905  type_stack = &ctx->stacks.stack;\
16906  NK_ASSERT(type_stack->head > 0);\
16907  if (type_stack->head < 1)\
16908  return 0;\
16909  element = &type_stack->elements[--type_stack->head];\
16910  *element->address = element->old_value;\
16911  return 1;\
16912 }
16913 
16914 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
16915 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
16916 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
16917 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
16918 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
16919 
16920 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
16921 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats)
16922 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
16923 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags)
16924 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors)
16925 
16926 NK_API int
16927 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c)
16928 {
16929  struct nk_style *style;
16930  NK_ASSERT(ctx);
16931  if (!ctx) return 0;
16932  style = &ctx->style;
16933  if (style->cursors[c]) {
16934  style->cursor_active = style->cursors[c];
16935  return 1;
16936  }
16937  return 0;
16938 }
16939 
16940 NK_API void
16941 nk_style_show_cursor(struct nk_context *ctx)
16942 {
16943  ctx->style.cursor_visible = nk_true;
16944 }
16945 
16946 NK_API void
16947 nk_style_hide_cursor(struct nk_context *ctx)
16948 {
16949  ctx->style.cursor_visible = nk_false;
16950 }
16951 
16952 NK_API void
16953 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
16954  const struct nk_cursor *c)
16955 {
16956  struct nk_style *style;
16957  NK_ASSERT(ctx);
16958  if (!ctx) return;
16959  style = &ctx->style;
16960  style->cursors[cursor] = c;
16961 }
16962 
16963 NK_API void
16964 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors)
16965 {
16966  int i = 0;
16967  struct nk_style *style;
16968  NK_ASSERT(ctx);
16969  if (!ctx) return;
16970  style = &ctx->style;
16971  for (i = 0; i < NK_CURSOR_COUNT; ++i)
16972  style->cursors[i] = &cursors[i];
16973  style->cursor_visible = nk_true;
16974 }
16975 
16976 /* ===============================================================
16977  *
16978  * POOL
16979  *
16980  * ===============================================================*/
16981 NK_INTERN void
16982 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
16983  unsigned int capacity)
16984 {
16985  nk_zero(pool, sizeof(*pool));
16986  pool->alloc = *alloc;
16987  pool->capacity = capacity;
16988  pool->type = NK_BUFFER_DYNAMIC;
16989  pool->pages = 0;
16990 }
16991 
16992 NK_INTERN void
16993 nk_pool_free(struct nk_pool *pool)
16994 {
16995  struct nk_page *iter = pool->pages;
16996  if (!pool) return;
16997  if (pool->type == NK_BUFFER_FIXED) return;
16998  while (iter) {
16999  struct nk_page *next = iter->next;
17000  pool->alloc.free(pool->alloc.userdata, iter);
17001  iter = next;
17002  }
17003 }
17004 
17005 NK_INTERN void
17006 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
17007 {
17008  nk_zero(pool, sizeof(*pool));
17009  NK_ASSERT(size >= sizeof(struct nk_page));
17010  if (size < sizeof(struct nk_page)) return;
17011  pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element);
17012  pool->pages = (struct nk_page*)memory;
17013  pool->type = NK_BUFFER_FIXED;
17014  pool->size = size;
17015 }
17016 
17017 NK_INTERN struct nk_page_element*
17018 nk_pool_alloc(struct nk_pool *pool)
17019 {
17020  if (!pool->pages || pool->pages->size >= pool->capacity) {
17021  /* allocate new page */
17022  struct nk_page *page;
17023  if (pool->type == NK_BUFFER_FIXED) {
17024  if (!pool->pages) {
17025  NK_ASSERT(pool->pages);
17026  return 0;
17027  }
17028  NK_ASSERT(pool->pages->size < pool->capacity);
17029  return 0;
17030  } else {
17031  nk_size size = sizeof(struct nk_page);
17032  size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data);
17033  page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
17034  page->next = pool->pages;
17035  pool->pages = page;
17036  page->size = 0;
17037  }
17038  }
17039  return &pool->pages->win[pool->pages->size++];
17040 }
17041 
17042 /* ===============================================================
17043  *
17044  * CONTEXT
17045  *
17046  * ===============================================================*/
17047 NK_INTERN void* nk_create_window(struct nk_context *ctx);
17048 NK_INTERN void nk_remove_window(struct nk_context*, struct nk_window*);
17049 NK_INTERN void nk_free_window(struct nk_context *ctx, struct nk_window *win);
17050 NK_INTERN void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
17051 NK_INTERN void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
17052 NK_INTERN void* nk_create_panel(struct nk_context *ctx);
17053 NK_INTERN void nk_free_panel(struct nk_context*, struct nk_panel *pan);
17054 
17055 NK_INTERN void
17056 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
17057 {
17058  NK_ASSERT(ctx);
17059  if (!ctx) return;
17060  nk_zero_struct(*ctx);
17061  nk_style_default(ctx);
17062  ctx->seq = 1;
17063  if (font) ctx->style.font = font;
17064 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
17065  nk_draw_list_init(&ctx->draw_list);
17066 #endif
17067 }
17068 
17069 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
17070 NK_API int
17071 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
17072 {
17073  struct nk_allocator alloc;
17074  alloc.userdata.ptr = 0;
17075  alloc.alloc = nk_malloc;
17076  alloc.free = nk_mfree;
17077  return nk_init(ctx, &alloc, font);
17078 }
17079 #endif
17080 
17081 NK_API int
17082 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
17083  const struct nk_user_font *font)
17084 {
17085  NK_ASSERT(memory);
17086  if (!memory) return 0;
17087  nk_setup(ctx, font);
17088  nk_buffer_init_fixed(&ctx->memory, memory, size);
17089  ctx->use_pool = nk_false;
17090  return 1;
17091 }
17092 
17093 NK_API int
17094 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
17095  struct nk_buffer *pool, const struct nk_user_font *font)
17096 {
17097  NK_ASSERT(cmds);
17098  NK_ASSERT(pool);
17099  if (!cmds || !pool) return 0;
17100 
17101  nk_setup(ctx, font);
17102  ctx->memory = *cmds;
17103  if (pool->type == NK_BUFFER_FIXED) {
17104  /* take memory from buffer and alloc fixed pool */
17105  nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
17106  } else {
17107  /* create dynamic pool from buffer allocator */
17108  struct nk_allocator *alloc = &pool->pool;
17109  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
17110  }
17111  ctx->use_pool = nk_true;
17112  return 1;
17113 }
17114 
17115 NK_API int
17116 nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
17117  const struct nk_user_font *font)
17118 {
17119  NK_ASSERT(alloc);
17120  if (!alloc) return 0;
17121  nk_setup(ctx, font);
17122  nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
17123  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
17124  ctx->use_pool = nk_true;
17125  return 1;
17126 }
17127 
17128 #ifdef NK_INCLUDE_COMMAND_USERDATA
17129 NK_API void
17130 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
17131 {
17132  if (!ctx) return;
17133  ctx->userdata = handle;
17134  if (ctx->current)
17135  ctx->current->buffer.userdata = handle;
17136 }
17137 #endif
17138 
17139 NK_API void
17140 nk_free(struct nk_context *ctx)
17141 {
17142  NK_ASSERT(ctx);
17143  if (!ctx) return;
17144  nk_buffer_free(&ctx->memory);
17145  if (ctx->use_pool)
17146  nk_pool_free(&ctx->pool);
17147 
17148  nk_zero(&ctx->input, sizeof(ctx->input));
17149  nk_zero(&ctx->style, sizeof(ctx->style));
17150  nk_zero(&ctx->memory, sizeof(ctx->memory));
17151 
17152  ctx->seq = 0;
17153  ctx->build = 0;
17154  ctx->begin = 0;
17155  ctx->end = 0;
17156  ctx->active = 0;
17157  ctx->current = 0;
17158  ctx->freelist = 0;
17159  ctx->count = 0;
17160 }
17161 
17162 NK_API void
17163 nk_clear(struct nk_context *ctx)
17164 {
17165  struct nk_window *iter;
17166  struct nk_window *next;
17167  NK_ASSERT(ctx);
17168 
17169  if (!ctx) return;
17170  if (ctx->use_pool)
17171  nk_buffer_clear(&ctx->memory);
17172  else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
17173 
17174  ctx->build = 0;
17175  ctx->memory.calls = 0;
17176  ctx->last_widget_state = 0;
17178  NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
17179 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
17180  nk_draw_list_clear(&ctx->draw_list);
17181 #endif
17182 
17183  /* garbage collector */
17184  iter = ctx->begin;
17185  while (iter) {
17186  /* make sure minimized windows do not get removed */
17187  if ((iter->flags & NK_WINDOW_MINIMIZED) &&
17188  !(iter->flags & NK_WINDOW_CLOSED)) {
17189  iter = iter->next;
17190  continue;
17191  }
17192 
17193  /* remove hotness from hidden or closed windows*/
17194  if (((iter->flags & NK_WINDOW_HIDDEN) ||
17195  (iter->flags & NK_WINDOW_CLOSED)) &&
17196  iter == ctx->active)
17197  ctx->active = iter->next;
17198 
17199  /* free unused popup windows */
17200  if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
17201  nk_free_window(ctx, iter->popup.win);
17202  iter->popup.win = 0;
17203  }
17204 
17205  /* remove unused window state tables */
17206  {struct nk_table *n, *it = iter->tables;
17207  while (it) {
17208  n = it->next;
17209  if (it->seq != ctx->seq) {
17210  nk_remove_table(iter, it);
17211  nk_zero(it, sizeof(union nk_page_data));
17212  nk_free_table(ctx, it);
17213  if (it == iter->tables)
17214  iter->tables = n;
17215  }
17216  it = n;
17217  }}
17218 
17219  /* window itself is not used anymore so free */
17220  if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
17221  next = iter->next;
17222  nk_remove_window(ctx, iter);
17223  nk_free_window(ctx, iter);
17224  iter = next;
17225  } else iter = iter->next;
17226  }
17227  ctx->seq++;
17228 }
17229 
17230 /* ----------------------------------------------------------------
17231  *
17232  * BUFFERING
17233  *
17234  * ---------------------------------------------------------------*/
17235 NK_INTERN void
17236 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
17237 {
17238  NK_ASSERT(ctx);
17239  NK_ASSERT(buffer);
17240  if (!ctx || !buffer) return;
17241  buffer->begin = ctx->memory.allocated;
17242  buffer->end = buffer->begin;
17243  buffer->last = buffer->begin;
17244  buffer->clip = nk_null_rect;
17245 }
17246 
17247 NK_INTERN void
17248 nk_start(struct nk_context *ctx, struct nk_window *win)
17249 {
17250  NK_ASSERT(ctx);
17251  NK_ASSERT(win);
17252  nk_start_buffer(ctx, &win->buffer);
17253 }
17254 
17255 NK_INTERN void
17256 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
17257 {
17258  struct nk_popup_buffer *buf;
17259  NK_ASSERT(ctx);
17260  NK_ASSERT(win);
17261  if (!ctx || !win) return;
17262 
17263  /* save buffer fill state for popup */
17264  buf = &win->popup.buf;
17265  buf->begin = win->buffer.end;
17266  buf->end = win->buffer.end;
17267  buf->parent = win->buffer.last;
17268  buf->last = buf->begin;
17269  buf->active = nk_true;
17270 }
17271 
17272 NK_INTERN void
17273 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
17274 {
17275  struct nk_popup_buffer *buf;
17276  NK_ASSERT(ctx);
17277  NK_ASSERT(win);
17278  if (!ctx || !win) return;
17279 
17280  buf = &win->popup.buf;
17281  buf->last = win->buffer.last;
17282  buf->end = win->buffer.end;
17283 }
17284 
17285 NK_INTERN void
17286 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
17287 {
17288  NK_ASSERT(ctx);
17289  NK_ASSERT(buffer);
17290  if (!ctx || !buffer) return;
17291  buffer->end = ctx->memory.allocated;
17292 }
17293 
17294 NK_INTERN void
17295 nk_finish(struct nk_context *ctx, struct nk_window *win)
17296 {
17297  struct nk_popup_buffer *buf;
17298  struct nk_command *parent_last;
17299  void *memory;
17300 
17301  NK_ASSERT(ctx);
17302  NK_ASSERT(win);
17303  if (!ctx || !win) return;
17304  nk_finish_buffer(ctx, &win->buffer);
17305  if (!win->popup.buf.active) return;
17306 
17307  buf = &win->popup.buf;
17308  memory = ctx->memory.memory.ptr;
17309  parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
17310  parent_last->next = buf->end;
17311 }
17312 
17313 NK_INTERN void
17314 nk_build(struct nk_context *ctx)
17315 {
17316  struct nk_window *iter = 0;
17317  struct nk_command *cmd = 0;
17318  nk_byte *buffer = 0;
17319 
17320  /* draw cursor overlay */
17321  if (!ctx->style.cursor_active)
17323  if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
17324  struct nk_rect mouse_bounds;
17325  const struct nk_cursor *cursor = ctx->style.cursor_active;
17326  nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
17327  nk_start_buffer(ctx, &ctx->overlay);
17328 
17329  mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
17330  mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
17331  mouse_bounds.w = cursor->size.x;
17332  mouse_bounds.h = cursor->size.y;
17333 
17334  nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
17335  nk_finish_buffer(ctx, &ctx->overlay);
17336  }
17337  /* build one big draw command list out of all window buffers */
17338  iter = ctx->begin;
17339  buffer = (nk_byte*)ctx->memory.memory.ptr;
17340  while (iter != 0) {
17341  struct nk_window *next = iter->next;
17342  if (iter->buffer.last == iter->buffer.begin || (iter->flags & NK_WINDOW_HIDDEN))
17343  goto cont;
17344 
17345  cmd = nk_ptr_add(struct nk_command, buffer, iter->buffer.last);
17346  while (next && ((next->buffer.last == next->buffer.begin) ||
17347  (next->flags & NK_WINDOW_HIDDEN)))
17348  next = next->next; /* skip empty command buffers */
17349 
17350  if (next) cmd->next = next->buffer.begin;
17351  cont: iter = next;
17352  }
17353  /* append all popup draw commands into lists */
17354  iter = ctx->begin;
17355  while (iter != 0) {
17356  struct nk_window *next = iter->next;
17357  struct nk_popup_buffer *buf;
17358  if (!iter->popup.buf.active)
17359  goto skip;
17360 
17361  buf = &iter->popup.buf;
17362  cmd->next = buf->begin;
17363  cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
17364  buf->active = nk_false;
17365  skip: iter = next;
17366  }
17367  /* append overlay commands */
17368  if (cmd) {
17369  if (ctx->overlay.end != ctx->overlay.begin)
17370  cmd->next = ctx->overlay.begin;
17371  else cmd->next = ctx->memory.allocated;
17372  }
17373 }
17374 
17375 NK_API const struct nk_command*
17376 nk__begin(struct nk_context *ctx)
17377 {
17378  struct nk_window *iter;
17379  nk_byte *buffer;
17380  NK_ASSERT(ctx);
17381  if (!ctx) return 0;
17382  if (!ctx->count) return 0;
17383 
17384  buffer = (nk_byte*)ctx->memory.memory.ptr;
17385  if (!ctx->build) {
17386  nk_build(ctx);
17387  ctx->build = nk_true;
17388  }
17389 
17390  iter = ctx->begin;
17391  while (iter && ((iter->buffer.begin == iter->buffer.end) || (iter->flags & NK_WINDOW_HIDDEN)))
17392  iter = iter->next;
17393  if (!iter) return 0;
17394  return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
17395 }
17396 
17397 NK_API const struct nk_command*
17398 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
17399 {
17400  nk_byte *buffer;
17401  const struct nk_command *next;
17402  NK_ASSERT(ctx);
17403  if (!ctx || !cmd || !ctx->count) return 0;
17404  if (cmd->next >= ctx->memory.allocated) return 0;
17405  buffer = (nk_byte*)ctx->memory.memory.ptr;
17406  next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
17407  return next;
17408 }
17409 
17410 /* ----------------------------------------------------------------
17411  *
17412  * PANEL
17413  *
17414  * ---------------------------------------------------------------*/
17415 static int
17416 nk_panel_has_header(nk_flags flags, const char *title)
17417 {
17418  int active = 0;
17419  active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
17420  active = active || (flags & NK_WINDOW_TITLE);
17421  active = active && !(flags & NK_WINDOW_HIDDEN) && title;
17422  return active;
17423 }
17424 
17425 NK_INTERN struct nk_vec2
17426 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
17427 {
17428  switch (type) {
17429  default:
17430  case NK_PANEL_WINDOW: return style->window.padding;
17431  case NK_PANEL_GROUP: return style->window.group_padding;
17432  case NK_PANEL_POPUP: return style->window.popup_padding;
17433  case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
17434  case NK_PANEL_COMBO: return style->window.combo_padding;
17435  case NK_PANEL_MENU: return style->window.menu_padding;
17436  case NK_PANEL_TOOLTIP: return style->window.menu_padding;
17437  }
17438 }
17439 
17440 NK_INTERN float
17441 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
17442  enum nk_panel_type type)
17443 {
17444  if (flags & NK_WINDOW_BORDER) {
17445  switch (type) {
17446  default:
17447  case NK_PANEL_WINDOW: return style->window.border;
17448  case NK_PANEL_GROUP: return style->window.group_border;
17449  case NK_PANEL_POPUP: return style->window.popup_border;
17450  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
17451  case NK_PANEL_COMBO: return style->window.combo_border;
17452  case NK_PANEL_MENU: return style->window.menu_border;
17453  case NK_PANEL_TOOLTIP: return style->window.menu_border;
17454  }} else return 0;
17455 }
17456 
17457 NK_INTERN struct nk_color
17458 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
17459 {
17460  switch (type) {
17461  default:
17462  case NK_PANEL_WINDOW: return style->window.border_color;
17463  case NK_PANEL_GROUP: return style->window.group_border_color;
17464  case NK_PANEL_POPUP: return style->window.popup_border_color;
17465  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
17466  case NK_PANEL_COMBO: return style->window.combo_border_color;
17467  case NK_PANEL_MENU: return style->window.menu_border_color;
17468  case NK_PANEL_TOOLTIP: return style->window.menu_border_color;
17469  }
17470 }
17471 
17472 NK_INTERN int
17473 nk_panel_is_sub(enum nk_panel_type type)
17474 {
17475  return (type & NK_PANEL_SET_SUB)?1:0;
17476 }
17477 
17478 NK_INTERN int
17479 nk_panel_is_nonblock(enum nk_panel_type type)
17480 {
17481  return (type & NK_PANEL_SET_NONBLOCK)?1:0;
17482 }
17483 
17484 NK_INTERN int
17485 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
17486 {
17487  struct nk_input *in;
17488  struct nk_window *win;
17489  struct nk_panel *layout;
17490  struct nk_command_buffer *out;
17491  const struct nk_style *style;
17492  const struct nk_user_font *font;
17493 
17494  struct nk_vec2 scrollbar_size;
17495  struct nk_vec2 panel_padding;
17496 
17497  NK_ASSERT(ctx);
17498  NK_ASSERT(ctx->current);
17499  NK_ASSERT(ctx->current->layout);
17500  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
17501  nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
17502  if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
17503  nk_zero(ctx->current->layout, sizeof(struct nk_panel));
17504  ctx->current->layout->type = panel_type;
17505  return 0;
17506  }
17507  /* pull state into local stack */
17508  style = &ctx->style;
17509  font = style->font;
17510  win = ctx->current;
17511  layout = win->layout;
17512  out = &win->buffer;
17513  in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
17514 #ifdef NK_INCLUDE_COMMAND_USERDATA
17515  win->buffer.userdata = ctx->userdata;
17516 #endif
17517  /* pull style configuration into local stack */
17518  scrollbar_size = style->window.scrollbar_size;
17519  panel_padding = nk_panel_get_padding(style, panel_type);
17520 
17521  /* window movement */
17522  if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
17523  int left_mouse_down;
17524  int left_mouse_click_in_cursor;
17525 
17526  /* calculate draggable window space */
17527  struct nk_rect header;
17528  header.x = win->bounds.x;
17529  header.y = win->bounds.y;
17530  header.w = win->bounds.w;
17531  if (nk_panel_has_header(win->flags, title)) {
17532  header.h = font->height + 2.0f * style->window.header.padding.y;
17533  header.h += 2.0f * style->window.header.label_padding.y;
17534  } else header.h = panel_padding.y;
17535 
17536  /* window movement by dragging */
17537  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
17538  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
17539  NK_BUTTON_LEFT, header, nk_true);
17540  if (left_mouse_down && left_mouse_click_in_cursor) {
17541  win->bounds.x = win->bounds.x + in->mouse.delta.x;
17542  win->bounds.y = win->bounds.y + in->mouse.delta.y;
17546  }
17547  }
17548 
17549  /* setup panel */
17550  layout->type = panel_type;
17551  layout->flags = win->flags;
17552  layout->bounds = win->bounds;
17553  layout->bounds.x += panel_padding.x;
17554  layout->bounds.w -= 2*panel_padding.x;
17555  if (win->flags & NK_WINDOW_BORDER) {
17556  layout->border = nk_panel_get_border(style, win->flags, panel_type);
17557  layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
17558  } else layout->border = 0;
17559  layout->at_y = layout->bounds.y;
17560  layout->at_x = layout->bounds.x;
17561  layout->max_x = 0;
17562  layout->header_height = 0;
17563  layout->footer_height = 0;
17564  layout->row.index = 0;
17565  layout->row.columns = 0;
17566  layout->row.ratio = 0;
17567  layout->row.item_width = 0;
17568  layout->row.tree_depth = 0;
17569  layout->row.height = panel_padding.y;
17570  layout->has_scrolling = nk_true;
17571  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
17572  layout->bounds.w -= scrollbar_size.x;
17573  if (!nk_panel_is_nonblock(panel_type)) {
17574  layout->footer_height = 0;
17575  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
17576  layout->footer_height = scrollbar_size.y;
17577  layout->bounds.h -= layout->footer_height;
17578  }
17579 
17580  /* panel header */
17581  if (nk_panel_has_header(win->flags, title))
17582  {
17583  struct nk_text text;
17584  struct nk_rect header;
17585  const struct nk_style_item *background = 0;
17586 
17587  /* calculate header bounds */
17588  header.x = win->bounds.x;
17589  header.y = win->bounds.y;
17590  header.w = win->bounds.w;
17591  header.h = font->height + 2.0f * style->window.header.padding.y;
17592  header.h += (2.0f * style->window.header.label_padding.y);
17593 
17594  /* shrink panel by header */
17595  layout->header_height = header.h;
17596  layout->bounds.y += header.h;
17597  layout->bounds.h -= header.h;
17598  layout->at_y += header.h;
17599 
17600  /* select correct header background and text color */
17601  if (ctx->active == win) {
17602  background = &style->window.header.active;
17603  text.text = style->window.header.label_active;
17604  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
17605  background = &style->window.header.hover;
17606  text.text = style->window.header.label_hover;
17607  } else {
17608  background = &style->window.header.normal;
17609  text.text = style->window.header.label_normal;
17610  }
17611 
17612  /* draw header background */
17613  header.h += 1.0f;
17614  if (background->type == NK_STYLE_ITEM_IMAGE) {
17615  text.background = nk_rgba(0,0,0,0);
17616  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
17617  } else {
17618  text.background = background->data.color;
17619  nk_fill_rect(out, header, 0, background->data.color);
17620  }
17621 
17622  /* window close button */
17623  {struct nk_rect button;
17624  button.y = header.y + style->window.header.padding.y;
17625  button.h = header.h - 2 * style->window.header.padding.y;
17626  button.w = button.h;
17627  if (win->flags & NK_WINDOW_CLOSABLE) {
17628  nk_flags ws = 0;
17629  if (style->window.header.align == NK_HEADER_RIGHT) {
17630  button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
17631  header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
17632  } else {
17633  button.x = header.x + style->window.header.padding.x;
17634  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
17635  }
17636 
17637  if (nk_do_button_symbol(&ws, &win->buffer, button,
17639  &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
17640  {
17641  layout->flags |= NK_WINDOW_HIDDEN;
17642  layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
17643  }
17644  }
17645 
17646  /* window minimize button */
17647  if (win->flags & NK_WINDOW_MINIMIZABLE) {
17648  nk_flags ws = 0;
17649  if (style->window.header.align == NK_HEADER_RIGHT) {
17650  button.x = (header.w + header.x) - button.w;
17651  if (!(win->flags & NK_WINDOW_CLOSABLE)) {
17652  button.x -= style->window.header.padding.x;
17653  header.w -= style->window.header.padding.x;
17654  }
17655  header.w -= button.w + style->window.header.spacing.x;
17656  } else {
17657  button.x = header.x;
17658  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
17659  }
17660  if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
17662  NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
17663  layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
17664  layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
17665  layout->flags | NK_WINDOW_MINIMIZED;
17666  }}
17667 
17668  {/* window header title */
17669  int text_len = nk_strlen(title);
17670  struct nk_rect label = {0,0,0,0};
17671  float t = font->width(font->userdata, font->height, title, text_len);
17672  text.padding = nk_vec2(0,0);
17673 
17674  label.x = header.x + style->window.header.padding.x;
17675  label.x += style->window.header.label_padding.x;
17676  label.y = header.y + style->window.header.label_padding.y;
17677  label.h = font->height + 2 * style->window.header.label_padding.y;
17678  label.w = t + 2 * style->window.header.spacing.x;
17679  label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
17680  nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
17681  }
17682 
17683  /* draw window background */
17684  if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
17685  struct nk_rect body;
17686  body.x = win->bounds.x;
17687  body.w = win->bounds.w;
17688  body.y = (win->bounds.y + layout->header_height);
17689  body.h = (win->bounds.h - layout->header_height);
17691  nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
17692  else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
17693  }
17694 
17695  /* set clipping rectangle */
17696  {struct nk_rect clip;
17697  layout->clip = layout->bounds;
17698  nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
17699  layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
17700  nk_push_scissor(out, clip);
17701  layout->clip = clip;}
17702  return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
17703 }
17704 
17705 NK_INTERN void
17706 nk_panel_end(struct nk_context *ctx)
17707 {
17708  struct nk_input *in;
17709  struct nk_window *window;
17710  struct nk_panel *layout;
17711  const struct nk_style *style;
17712  struct nk_command_buffer *out;
17713 
17714  struct nk_vec2 scrollbar_size;
17715  struct nk_vec2 panel_padding;
17716 
17717  NK_ASSERT(ctx);
17718  NK_ASSERT(ctx->current);
17719  NK_ASSERT(ctx->current->layout);
17720  if (!ctx || !ctx->current || !ctx->current->layout)
17721  return;
17722 
17723  window = ctx->current;
17724  layout = window->layout;
17725  style = &ctx->style;
17726  out = &window->buffer;
17727  in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
17728  if (!nk_panel_is_sub(layout->type))
17729  nk_push_scissor(out, nk_null_rect);
17730 
17731  /* cache configuration data */
17732  scrollbar_size = style->window.scrollbar_size;
17733  panel_padding = nk_panel_get_padding(style, layout->type);
17734 
17735  /* update the current cursor Y-position to point over the last added widget */
17736  layout->at_y += layout->row.height;
17737 
17738  /* dynamic panels */
17739  if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
17740  {
17741  /* update panel height to fit dynamic growth */
17742  struct nk_rect empty_space;
17743  if (layout->at_y < (layout->bounds.y + layout->bounds.h))
17744  layout->bounds.h = layout->at_y - layout->bounds.y;
17745 
17746  /* fill top empty space */
17747  empty_space.x = window->bounds.x;
17748  empty_space.y = layout->bounds.y;
17749  empty_space.h = panel_padding.y;
17750  empty_space.w = window->bounds.w;
17751  nk_fill_rect(out, empty_space, 0, style->window.background);
17752 
17753  /* fill left empty space */
17754  empty_space.x = window->bounds.x;
17755  empty_space.y = layout->bounds.y;
17756  empty_space.w = panel_padding.x + layout->border;
17757  empty_space.h = layout->bounds.h;
17758  nk_fill_rect(out, empty_space, 0, style->window.background);
17759 
17760  /* fill right empty space */
17761  empty_space.x = layout->bounds.x + layout->bounds.w - layout->border;
17762  empty_space.y = layout->bounds.y;
17763  empty_space.w = panel_padding.x + layout->border;
17764  empty_space.h = layout->bounds.h;
17765  if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
17766  empty_space.w += scrollbar_size.x;
17767  nk_fill_rect(out, empty_space, 0, style->window.background);
17768 
17769  /* fill bottom empty space */
17770  if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) {
17771  empty_space.x = window->bounds.x;
17772  empty_space.y = layout->bounds.y + layout->bounds.h;
17773  empty_space.w = window->bounds.w;
17774  empty_space.h = scrollbar_size.y;
17775  nk_fill_rect(out, empty_space, 0, style->window.background);
17776  }
17777  }
17778 
17779  /* scrollbars */
17780  if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
17781  !(layout->flags & NK_WINDOW_MINIMIZED) &&
17783  {
17784  struct nk_rect scroll;
17785  int scroll_has_scrolling;
17786  float scroll_target;
17787  float scroll_offset;
17788  float scroll_step;
17789  float scroll_inc;
17790 
17791  /* mouse wheel scrolling */
17792  if (nk_panel_is_sub(layout->type))
17793  {
17794  /* sub-window mouse wheel scrolling */
17795  struct nk_window *root_window = window;
17796  struct nk_panel *root_panel = window->layout;
17797  while (root_panel->parent)
17798  root_panel = root_panel->parent;
17799  while (root_window->parent)
17800  root_window = root_window->parent;
17801 
17802  /* only allow scrolling if parent window is active */
17803  scroll_has_scrolling = 0;
17804  if ((root_window == ctx->active) && layout->has_scrolling) {
17805  /* and panel is being hovered and inside clip rect*/
17806  if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
17807  NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
17808  root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
17809  {
17810  /* deactivate all parent scrolling */
17811  root_panel = window->layout;
17812  while (root_panel->parent) {
17813  root_panel->has_scrolling = nk_false;
17814  root_panel = root_panel->parent;
17815  }
17816  root_panel->has_scrolling = nk_false;
17817  scroll_has_scrolling = nk_true;
17818  }
17819  }
17820  } else if (!nk_panel_is_sub(layout->type)) {
17821  /* window mouse wheel scrolling */
17822  scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
17823  if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
17824  window->scrolled = nk_true;
17825  else window->scrolled = nk_false;
17826  } else scroll_has_scrolling = nk_false;
17827 
17828  {
17829  /* vertical scrollbar */
17830  nk_flags state = 0;
17831  scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
17832  scroll.y = layout->bounds.y;
17833  scroll.w = scrollbar_size.x;
17834  scroll.h = layout->bounds.h;
17835 
17836  scroll_offset = (float)*layout->offset_y;
17837  scroll_step = scroll.h * 0.10f;
17838  scroll_inc = scroll.h * 0.01f;
17839  scroll_target = (float)(int)(layout->at_y - scroll.y);
17840  scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
17841  scroll_offset, scroll_target, scroll_step, scroll_inc,
17842  &ctx->style.scrollv, in, style->font);
17843  *layout->offset_y = (nk_uint)scroll_offset;
17844  if (in && scroll_has_scrolling)
17845  in->mouse.scroll_delta.y = 0;
17846  }
17847  {
17848  /* horizontal scrollbar */
17849  nk_flags state = 0;
17850  scroll.x = layout->bounds.x;
17851  scroll.y = layout->bounds.y + layout->bounds.h;
17852  scroll.w = layout->bounds.w;
17853  scroll.h = scrollbar_size.y;
17854 
17855  scroll_offset = (float)*layout->offset_x;
17856  scroll_target = (float)(int)(layout->max_x - scroll.x);
17857  scroll_step = layout->max_x * 0.05f;
17858  scroll_inc = layout->max_x * 0.005f;
17859  scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
17860  scroll_offset, scroll_target, scroll_step, scroll_inc,
17861  &ctx->style.scrollh, in, style->font);
17862  *layout->offset_x = (nk_uint)scroll_offset;
17863  }
17864  }
17865 
17866  /* hide scroll if no user input */
17867  if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
17868  int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
17869  int is_window_hovered = nk_window_is_hovered(ctx);
17870  int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
17871  if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
17873  else window->scrollbar_hiding_timer = 0;
17874  } else window->scrollbar_hiding_timer = 0;
17875 
17876  /* window border */
17877  if (layout->flags & NK_WINDOW_BORDER)
17878  {
17879  struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
17880  const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) ?
17881  style->window.border + window->bounds.y + layout->header_height:
17882  (layout->flags & NK_WINDOW_DYNAMIC)?
17883  layout->bounds.y + layout->bounds.h + layout->footer_height:
17884  window->bounds.y + window->bounds.h;
17885 
17886  /* draw border top */
17887  nk_stroke_line(out,window->bounds.x,window->bounds.y,
17888  window->bounds.x + window->bounds.w, window->bounds.y,
17889  layout->border, border_color);
17890 
17891  /* draw bottom border */
17892  nk_stroke_line(out, window->bounds.x, padding_y,
17893  window->bounds.x + window->bounds.w, padding_y, layout->border, border_color);
17894 
17895  /* draw left border */
17896  nk_stroke_line(out, window->bounds.x + layout->border*0.5f,
17897  window->bounds.y, window->bounds.x + layout->border*0.5f,
17898  padding_y, layout->border, border_color);
17899 
17900  /* draw right border */
17901  nk_stroke_line(out, window->bounds.x + window->bounds.w - layout->border*0.5f,
17902  window->bounds.y, window->bounds.x + window->bounds.w - layout->border*0.5f,
17903  padding_y, layout->border, border_color);
17904  }
17905 
17906  /* scaler */
17907  if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
17908  {
17909  /* calculate scaler bounds */
17910  struct nk_rect scaler;
17911  scaler.w = scrollbar_size.x;
17912  scaler.h = scrollbar_size.y;
17913  scaler.y = layout->bounds.y + layout->bounds.h;
17914  if (layout->flags & NK_WINDOW_SCALE_LEFT)
17915  scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
17916  else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
17917  if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
17918  scaler.x -= scaler.w;
17919 
17920  /* draw scaler */
17921  {const struct nk_style_item *item = &style->window.scaler;
17922  if (item->type == NK_STYLE_ITEM_IMAGE)
17923  nk_draw_image(out, scaler, &item->data.image, nk_white);
17924  else {
17925  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
17926  nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
17927  scaler.y + scaler.h, scaler.x + scaler.w,
17928  scaler.y + scaler.h, item->data.color);
17929  } else {
17930  nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
17931  scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
17932  }
17933  }}
17934 
17935  /* do window scaling */
17936  if (!(window->flags & NK_WINDOW_ROM)) {
17937  struct nk_vec2 window_size = style->window.min_size;
17938  int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
17939  int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
17940  NK_BUTTON_LEFT, scaler, nk_true);
17941 
17942  if (left_mouse_down && left_mouse_click_in_scaler) {
17943  float delta_x = in->mouse.delta.x;
17944  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
17945  delta_x = -delta_x;
17946  window->bounds.x += in->mouse.delta.x;
17947  }
17948  /* dragging in x-direction */
17949  if (window->bounds.w + delta_x >= window_size.x) {
17950  if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
17951  window->bounds.w = window->bounds.w + delta_x;
17952  scaler.x += in->mouse.delta.x;
17953  }
17954  }
17955  /* dragging in y-direction (only possible if static window) */
17956  if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
17957  if (window_size.y < window->bounds.h + in->mouse.delta.y) {
17958  if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
17959  window->bounds.h = window->bounds.h + in->mouse.delta.y;
17960  scaler.y += in->mouse.delta.y;
17961  }
17962  }
17963  }
17965  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
17966  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
17967  }
17968  }
17969  }
17970  if (!nk_panel_is_sub(layout->type)) {
17971  /* window is hidden so clear command buffer */
17972  if (layout->flags & NK_WINDOW_HIDDEN)
17973  nk_command_buffer_reset(&window->buffer);
17974  /* window is visible and not tab */
17975  else nk_finish(ctx, window);
17976  }
17977 
17978  /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
17979  if (layout->flags & NK_WINDOW_REMOVE_ROM) {
17980  layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
17981  layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
17982  }
17983  window->flags = layout->flags;
17984 
17985  /* property garbage collector */
17986  if (window->property.active && window->property.old != window->property.seq &&
17987  window->property.active == window->property.prev) {
17988  nk_zero(&window->property, sizeof(window->property));
17989  } else {
17990  window->property.old = window->property.seq;
17991  window->property.prev = window->property.active;
17992  window->property.seq = 0;
17993  }
17994  /* edit garbage collector */
17995  if (window->edit.active && window->edit.old != window->edit.seq &&
17996  window->edit.active == window->edit.prev) {
17997  nk_zero(&window->edit, sizeof(window->edit));
17998  } else {
17999  window->edit.old = window->edit.seq;
18000  window->edit.prev = window->edit.active;
18001  window->edit.seq = 0;
18002  }
18003  /* contextual garbage collector */
18004  if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
18005  window->popup.con_count = 0;
18006  window->popup.con_old = 0;
18007  window->popup.active_con = 0;
18008  } else {
18009  window->popup.con_old = window->popup.con_count;
18010  window->popup.con_count = 0;
18011  }
18012  window->popup.combo_count = 0;
18013  /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
18014  NK_ASSERT(!layout->row.tree_depth);
18015 }
18016 
18017 /* ----------------------------------------------------------------
18018  *
18019  * PAGE ELEMENT
18020  *
18021  * ---------------------------------------------------------------*/
18022 NK_INTERN struct nk_page_element*
18023 nk_create_page_element(struct nk_context *ctx)
18024 {
18025  struct nk_page_element *elem;
18026  if (ctx->freelist) {
18027  /* unlink page element from free list */
18028  elem = ctx->freelist;
18029  ctx->freelist = elem->next;
18030  } else if (ctx->use_pool) {
18031  /* allocate page element from memory pool */
18032  elem = nk_pool_alloc(&ctx->pool);
18033  NK_ASSERT(elem);
18034  if (!elem) return 0;
18035  } else {
18036  /* allocate new page element from back of fixed size memory buffer */
18037  NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
18038  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
18039  elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
18040  NK_ASSERT(elem);
18041  if (!elem) return 0;
18042  }
18043  nk_zero_struct(*elem);
18044  elem->next = 0;
18045  elem->prev = 0;
18046  return elem;
18047 }
18048 
18049 NK_INTERN void
18050 nk_link_page_element_into_freelist(struct nk_context *ctx,
18051  struct nk_page_element *elem)
18052 {
18053  /* link table into freelist */
18054  if (!ctx->freelist) {
18055  ctx->freelist = elem;
18056  } else {
18057  elem->next = ctx->freelist;
18058  ctx->freelist = elem;
18059  }
18060 }
18061 
18062 NK_INTERN void
18063 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
18064 {
18065  /* we have a pool so just add to free list */
18066  if (ctx->use_pool) {
18067  nk_link_page_element_into_freelist(ctx, elem);
18068  return;
18069  }
18070  /* if possible remove last element from back of fixed memory buffer */
18071  {void *elem_end = (void*)(elem + 1);
18072  void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
18073  if (elem_end == buffer_end)
18074  ctx->memory.size -= sizeof(struct nk_page_element);
18075  else nk_link_page_element_into_freelist(ctx, elem);}
18076 }
18077 
18078 /* ----------------------------------------------------------------
18079  *
18080  * PANEL
18081  *
18082  * ---------------------------------------------------------------*/
18083 NK_INTERN void*
18084 nk_create_panel(struct nk_context *ctx)
18085 {
18086  struct nk_page_element *elem;
18087  elem = nk_create_page_element(ctx);
18088  if (!elem) return 0;
18089  nk_zero_struct(*elem);
18090  return &elem->data.pan;
18091 }
18092 
18093 NK_INTERN void
18094 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
18095 {
18096  union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
18097  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18098  nk_free_page_element(ctx, pe);
18099 }
18100 
18101 /* ----------------------------------------------------------------
18102  *
18103  * TABLES
18104  *
18105  * ---------------------------------------------------------------*/
18106 NK_INTERN struct nk_table*
18107 nk_create_table(struct nk_context *ctx)
18108 {
18109  struct nk_page_element *elem;
18110  elem = nk_create_page_element(ctx);
18111  if (!elem) return 0;
18112  nk_zero_struct(*elem);
18113  return &elem->data.tbl;
18114 }
18115 
18116 NK_INTERN void
18117 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
18118 {
18119  union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
18120  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18121  nk_free_page_element(ctx, pe);
18122 }
18123 
18124 NK_INTERN void
18125 nk_push_table(struct nk_window *win, struct nk_table *tbl)
18126 {
18127  if (!win->tables) {
18128  win->tables = tbl;
18129  tbl->next = 0;
18130  tbl->prev = 0;
18131  win->table_count = 1;
18132  win->table_size = 0;
18133  return;
18134  }
18135  win->tables->prev = tbl;
18136  tbl->next = win->tables;
18137  tbl->prev = 0;
18138  win->tables = tbl;
18139  win->table_count++;
18140  win->table_size = 0;
18141 }
18142 
18143 NK_INTERN void
18144 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
18145 {
18146  if (win->tables == tbl)
18147  win->tables = tbl->next;
18148  if (tbl->next)
18149  tbl->next->prev = tbl->prev;
18150  if (tbl->prev)
18151  tbl->prev->next = tbl->next;
18152  tbl->next = 0;
18153  tbl->prev = 0;
18154 }
18155 
18156 NK_INTERN nk_uint*
18157 nk_add_value(struct nk_context *ctx, struct nk_window *win,
18158  nk_hash name, nk_uint value)
18159 {
18160  NK_ASSERT(ctx);
18161  NK_ASSERT(win);
18162  if (!win || !ctx) return 0;
18163  if (!win->tables || win->table_size >= NK_VALUE_PAGE_CAPACITY) {
18164  struct nk_table *tbl = nk_create_table(ctx);
18165  NK_ASSERT(tbl);
18166  if (!tbl) return 0;
18167  nk_push_table(win, tbl);
18168  }
18169  win->tables->seq = win->seq;
18170  win->tables->keys[win->table_size] = name;
18171  win->tables->values[win->table_size] = value;
18172  return &win->tables->values[win->table_size++];
18173 }
18174 
18175 NK_INTERN nk_uint*
18176 nk_find_value(struct nk_window *win, nk_hash name)
18177 {
18178  nk_ushort size = win->table_size;
18179  struct nk_table *iter = win->tables;
18180  while (iter) {
18181  nk_ushort i = 0;
18182  for (i = 0; i < size; ++i) {
18183  if (iter->keys[i] == name) {
18184  iter->seq = win->seq;
18185  return &iter->values[i];
18186  }
18187  }
18188  size = NK_VALUE_PAGE_CAPACITY;
18189  iter = iter->next;
18190  }
18191  return 0;
18192 }
18193 
18194 /* ----------------------------------------------------------------
18195  *
18196  * WINDOW
18197  *
18198  * ---------------------------------------------------------------*/
18199 NK_INTERN void*
18200 nk_create_window(struct nk_context *ctx)
18201 {
18202  struct nk_page_element *elem;
18203  elem = nk_create_page_element(ctx);
18204  if (!elem) return 0;
18205  elem->data.win.seq = ctx->seq;
18206  return &elem->data.win;
18207 }
18208 
18209 NK_INTERN void
18210 nk_free_window(struct nk_context *ctx, struct nk_window *win)
18211 {
18212  /* unlink windows from list */
18213  struct nk_table *it = win->tables;
18214  if (win->popup.win) {
18215  nk_free_window(ctx, win->popup.win);
18216  win->popup.win = 0;
18217  }
18218  win->next = 0;
18219  win->prev = 0;
18220 
18221  while (it) {
18222  /*free window state tables */
18223  struct nk_table *n = it->next;
18224  nk_remove_table(win, it);
18225  nk_free_table(ctx, it);
18226  if (it == win->tables)
18227  win->tables = n;
18228  it = n;
18229  }
18230 
18231  /* link windows into freelist */
18232  {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
18233  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18234  nk_free_page_element(ctx, pe);}
18235 }
18236 
18237 NK_INTERN struct nk_window*
18238 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
18239 {
18240  struct nk_window *iter;
18241  iter = ctx->begin;
18242  while (iter) {
18243  NK_ASSERT(iter != iter->next);
18244  if (iter->name == hash) {
18245  int max_len = nk_strlen(iter->name_string);
18246  if (!nk_stricmpn(iter->name_string, name, max_len))
18247  return iter;
18248  }
18249  iter = iter->next;
18250  }
18251  return 0;
18252 }
18253 
18254 enum nk_window_insert_location {
18255  NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
18256  NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
18257 };
18258 NK_INTERN void
18259 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
18260  enum nk_window_insert_location loc)
18261 {
18262  const struct nk_window *iter;
18263  NK_ASSERT(ctx);
18264  NK_ASSERT(win);
18265  if (!win || !ctx) return;
18266 
18267  iter = ctx->begin;
18268  while (iter) {
18269  NK_ASSERT(iter != iter->next);
18270  NK_ASSERT(iter != win);
18271  if (iter == win) return;
18272  iter = iter->next;
18273  }
18274 
18275  if (!ctx->begin) {
18276  win->next = 0;
18277  win->prev = 0;
18278  ctx->begin = win;
18279  ctx->end = win;
18280  ctx->count = 1;
18281  return;
18282  }
18283  if (loc == NK_INSERT_BACK) {
18284  struct nk_window *end;
18285  end = ctx->end;
18286  end->flags |= NK_WINDOW_ROM;
18287  end->next = win;
18288  win->prev = ctx->end;
18289  win->next = 0;
18290  ctx->end = win;
18291  ctx->active = ctx->end;
18292  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
18293  } else {
18294  ctx->end->flags |= NK_WINDOW_ROM;
18295  ctx->begin->prev = win;
18296  win->next = ctx->begin;
18297  win->prev = 0;
18298  ctx->begin = win;
18299  ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
18300  }
18301  ctx->count++;
18302 }
18303 
18304 NK_INTERN void
18305 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
18306 {
18307  if (win == ctx->begin || win == ctx->end) {
18308  if (win == ctx->begin) {
18309  ctx->begin = win->next;
18310  if (win->next)
18311  win->next->prev = 0;
18312  }
18313  if (win == ctx->end) {
18314  ctx->end = win->prev;
18315  if (win->prev)
18316  win->prev->next = 0;
18317  }
18318  } else {
18319  if (win->next)
18320  win->next->prev = win->prev;
18321  if (win->prev)
18322  win->prev->next = win->next;
18323  }
18324  if (win == ctx->active || !ctx->active) {
18325  ctx->active = ctx->end;
18326  if (ctx->end)
18327  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
18328  }
18329  win->next = 0;
18330  win->prev = 0;
18331  ctx->count--;
18332 }
18333 
18334 NK_API int
18335 nk_begin(struct nk_context *ctx, const char *title,
18336  struct nk_rect bounds, nk_flags flags)
18337 {
18338  return nk_begin_titled(ctx, title, title, bounds, flags);
18339 }
18340 
18341 NK_API int
18342 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
18343  struct nk_rect bounds, nk_flags flags)
18344 {
18345  struct nk_window *win;
18346  struct nk_style *style;
18347  nk_hash title_hash;
18348  int title_len;
18349  int ret = 0;
18350 
18351  NK_ASSERT(ctx);
18352  NK_ASSERT(name);
18353  NK_ASSERT(title);
18354  NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
18355  NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
18356  if (!ctx || ctx->current || !title || !name)
18357  return 0;
18358 
18359  /* find or create window */
18360  style = &ctx->style;
18361  title_len = (int)nk_strlen(name);
18362  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18363  win = nk_find_window(ctx, title_hash, name);
18364  if (!win) {
18365  /* create new window */
18366  nk_size name_length = (nk_size)nk_strlen(name);
18367  win = (struct nk_window*)nk_create_window(ctx);
18368  NK_ASSERT(win);
18369  if (!win) return 0;
18370 
18371  if (flags & NK_WINDOW_BACKGROUND)
18372  nk_insert_window(ctx, win, NK_INSERT_FRONT);
18373  else nk_insert_window(ctx, win, NK_INSERT_BACK);
18374  nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
18375 
18376  win->flags = flags;
18377  win->bounds = bounds;
18378  win->name = title_hash;
18379  name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
18380  NK_MEMCPY(win->name_string, name, name_length);
18381  win->name_string[name_length] = 0;
18382  win->popup.win = 0;
18383  if (!ctx->active)
18384  ctx->active = win;
18385  } else {
18386  /* update window */
18387  win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
18388  win->flags |= flags;
18389  if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
18390  win->bounds = bounds;
18391  /* If this assert triggers you either:
18392  *
18393  * I.) Have more than one window with the same name or
18394  * II.) You forgot to actually draw the window.
18395  * More specific you did not call `nk_clear` (nk_clear will be
18396  * automatically called for you if you are using one of the
18397  * provided demo backends). */
18398  NK_ASSERT(win->seq != ctx->seq);
18399  win->seq = ctx->seq;
18400  if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN))
18401  ctx->active = win;
18402  }
18403  if (win->flags & NK_WINDOW_HIDDEN) {
18404  ctx->current = win;
18405  win->layout = 0;
18406  return 0;
18407  }
18408 
18409  /* window overlapping */
18410  if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
18411  {
18412  int inpanel, ishovered;
18413  const struct nk_window *iter = win;
18414  float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
18415  (2.0f * style->window.header.label_padding.y);
18416  struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
18417  win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
18418 
18419  /* activate window if hovered and no other window is overlapping this window */
18420  nk_start(ctx, win);
18421  inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
18422  inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
18423  ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
18424  if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
18425  iter = win->next;
18426  while (iter) {
18427  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
18428  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
18429  if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18430  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
18431  (!(iter->flags & NK_WINDOW_HIDDEN) || !(iter->flags & NK_WINDOW_BACKGROUND)))
18432  break;
18433 
18434  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
18435  NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18436  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
18437  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
18438  break;
18439  iter = iter->next;
18440  }
18441  }
18442 
18443  /* activate window if clicked */
18444  if (iter && inpanel && (win != ctx->end) && !(iter->flags & NK_WINDOW_BACKGROUND)) {
18445  iter = win->next;
18446  while (iter) {
18447  /* try to find a panel with higher priority in the same position */
18448  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
18449  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
18450  if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
18451  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
18452  !(iter->flags & NK_WINDOW_HIDDEN))
18453  break;
18454  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
18455  NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18456  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
18457  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
18458  break;
18459  iter = iter->next;
18460  }
18461  }
18462 
18463  if (!iter && ctx->end != win) {
18464  if (!(win->flags & NK_WINDOW_BACKGROUND)) {
18465  /* current window is active in that position so transfer to top
18466  * at the highest priority in stack */
18467  nk_remove_window(ctx, win);
18468  nk_insert_window(ctx, win, NK_INSERT_BACK);
18469  }
18470  win->flags &= ~(nk_flags)NK_WINDOW_ROM;
18471  ctx->active = win;
18472  }
18473  if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
18474  win->flags |= NK_WINDOW_ROM;
18475  }
18476 
18477  win->layout = (struct nk_panel*)nk_create_panel(ctx);
18478  ctx->current = win;
18479  ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
18480  win->layout->offset_x = &win->scrollbar.x;
18481  win->layout->offset_y = &win->scrollbar.y;
18482  return ret;
18483 }
18484 
18485 NK_API void
18486 nk_end(struct nk_context *ctx)
18487 {
18488  struct nk_panel *layout;
18489  NK_ASSERT(ctx);
18490  NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
18491  if (!ctx || !ctx->current)
18492  return;
18493 
18494  layout = ctx->current->layout;
18495  if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
18496  ctx->current = 0;
18497  return;
18498  }
18499  nk_panel_end(ctx);
18500  nk_free_panel(ctx, ctx->current->layout);
18501  ctx->current = 0;
18502 }
18503 
18504 NK_API struct nk_rect
18506 {
18507  NK_ASSERT(ctx);
18508  NK_ASSERT(ctx->current);
18509  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
18510  return ctx->current->bounds;
18511 }
18512 
18513 NK_API struct nk_vec2
18515 {
18516  NK_ASSERT(ctx);
18517  NK_ASSERT(ctx->current);
18518  if (!ctx || !ctx->current) return nk_vec2(0,0);
18519  return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
18520 }
18521 
18522 NK_API struct nk_vec2
18524 {
18525  NK_ASSERT(ctx);
18526  NK_ASSERT(ctx->current);
18527  if (!ctx || !ctx->current) return nk_vec2(0,0);
18528  return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
18529 }
18530 
18531 NK_API float
18532 nk_window_get_width(const struct nk_context *ctx)
18533 {
18534  NK_ASSERT(ctx);
18535  NK_ASSERT(ctx->current);
18536  if (!ctx || !ctx->current) return 0;
18537  return ctx->current->bounds.w;
18538 }
18539 
18540 NK_API float
18541 nk_window_get_height(const struct nk_context *ctx)
18542 {
18543  NK_ASSERT(ctx);
18544  NK_ASSERT(ctx->current);
18545  if (!ctx || !ctx->current) return 0;
18546  return ctx->current->bounds.h;
18547 }
18548 
18549 NK_API struct nk_rect
18551 {
18552  NK_ASSERT(ctx);
18553  NK_ASSERT(ctx->current);
18554  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
18555  return ctx->current->layout->clip;
18556 }
18557 
18558 NK_API struct nk_vec2
18560 {
18561  NK_ASSERT(ctx);
18562  NK_ASSERT(ctx->current);
18563  NK_ASSERT(ctx->current->layout);
18564  if (!ctx || !ctx->current) return nk_vec2(0,0);
18565  return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
18566 }
18567 
18568 NK_API struct nk_vec2
18570 {
18571  NK_ASSERT(ctx);
18572  NK_ASSERT(ctx->current);
18573  NK_ASSERT(ctx->current->layout);
18574  if (!ctx || !ctx->current) return nk_vec2(0,0);
18575  return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
18576  ctx->current->layout->clip.y + ctx->current->layout->clip.h);
18577 }
18578 
18579 NK_API struct nk_vec2
18581 {
18582  NK_ASSERT(ctx);
18583  NK_ASSERT(ctx->current);
18584  NK_ASSERT(ctx->current->layout);
18585  if (!ctx || !ctx->current) return nk_vec2(0,0);
18586  return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
18587 }
18588 
18589 NK_API struct nk_command_buffer*
18590 nk_window_get_canvas(struct nk_context *ctx)
18591 {
18592  NK_ASSERT(ctx);
18593  NK_ASSERT(ctx->current);
18594  NK_ASSERT(ctx->current->layout);
18595  if (!ctx || !ctx->current) return 0;
18596  return &ctx->current->buffer;
18597 }
18598 
18599 NK_API struct nk_panel*
18600 nk_window_get_panel(struct nk_context *ctx)
18601 {
18602  NK_ASSERT(ctx);
18603  NK_ASSERT(ctx->current);
18604  if (!ctx || !ctx->current) return 0;
18605  return ctx->current->layout;
18606 }
18607 
18608 NK_API int
18609 nk_window_has_focus(const struct nk_context *ctx)
18610 {
18611  NK_ASSERT(ctx);
18612  NK_ASSERT(ctx->current);
18613  NK_ASSERT(ctx->current->layout);
18614  if (!ctx || !ctx->current) return 0;
18615  return ctx->current == ctx->active;
18616 }
18617 
18618 NK_API int
18619 nk_window_is_hovered(struct nk_context *ctx)
18620 {
18621  NK_ASSERT(ctx);
18622  NK_ASSERT(ctx->current);
18623  if (!ctx || !ctx->current) return 0;
18624  return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds);
18625 }
18626 
18627 NK_API int
18629 {
18630  struct nk_window *iter;
18631  NK_ASSERT(ctx);
18632  if (!ctx) return 0;
18633  iter = ctx->begin;
18634  while (iter) {
18635  /* check if window is being hovered */
18636  if (iter->flags & NK_WINDOW_MINIMIZED) {
18637  struct nk_rect header = iter->bounds;
18638  header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
18639  if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
18640  return 1;
18641  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
18642  return 1;
18643  }
18644  /* check if window popup is being hovered */
18645  if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
18646  return 1;
18647  iter = iter->next;
18648  }
18649  return 0;
18650 }
18651 
18652 NK_API int
18653 nk_item_is_any_active(struct nk_context *ctx)
18654 {
18655  int any_hovered = nk_window_is_any_hovered(ctx);
18656  int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
18657  return any_hovered || any_active;
18658 }
18659 
18660 NK_API int
18661 nk_window_is_collapsed(struct nk_context *ctx, const char *name)
18662 {
18663  int title_len;
18664  nk_hash title_hash;
18665  struct nk_window *win;
18666  NK_ASSERT(ctx);
18667  if (!ctx) return 0;
18668 
18669  title_len = (int)nk_strlen(name);
18670  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18671  win = nk_find_window(ctx, title_hash, name);
18672  if (!win) return 0;
18673  return win->flags & NK_WINDOW_MINIMIZED;
18674 }
18675 
18676 NK_API int
18677 nk_window_is_closed(struct nk_context *ctx, const char *name)
18678 {
18679  int title_len;
18680  nk_hash title_hash;
18681  struct nk_window *win;
18682  NK_ASSERT(ctx);
18683  if (!ctx) return 1;
18684 
18685  title_len = (int)nk_strlen(name);
18686  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18687  win = nk_find_window(ctx, title_hash, name);
18688  if (!win) return 1;
18689  return (win->flags & NK_WINDOW_CLOSED);
18690 }
18691 
18692 NK_API int
18693 nk_window_is_hidden(struct nk_context *ctx, const char *name)
18694 {
18695  int title_len;
18696  nk_hash title_hash;
18697  struct nk_window *win;
18698  NK_ASSERT(ctx);
18699  if (!ctx) return 1;
18700 
18701  title_len = (int)nk_strlen(name);
18702  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18703  win = nk_find_window(ctx, title_hash, name);
18704  if (!win) return 1;
18705  return (win->flags & NK_WINDOW_HIDDEN);
18706 }
18707 
18708 NK_API int
18709 nk_window_is_active(struct nk_context *ctx, const char *name)
18710 {
18711  int title_len;
18712  nk_hash title_hash;
18713  struct nk_window *win;
18714  NK_ASSERT(ctx);
18715  if (!ctx) return 0;
18716 
18717  title_len = (int)nk_strlen(name);
18718  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18719  win = nk_find_window(ctx, title_hash, name);
18720  if (!win) return 0;
18721  return win == ctx->active;
18722 }
18723 
18724 NK_API struct nk_window*
18725 nk_window_find(struct nk_context *ctx, const char *name)
18726 {
18727  int title_len;
18728  nk_hash title_hash;
18729  title_len = (int)nk_strlen(name);
18730  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18731  return nk_find_window(ctx, title_hash, name);
18732 }
18733 
18734 NK_API void
18735 nk_window_close(struct nk_context *ctx, const char *name)
18736 {
18737  struct nk_window *win;
18738  NK_ASSERT(ctx);
18739  if (!ctx) return;
18740  win = nk_window_find(ctx, name);
18741  if (!win) return;
18742  NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
18743  if (ctx->current == win) return;
18744  win->flags |= NK_WINDOW_HIDDEN;
18745  win->flags |= NK_WINDOW_CLOSED;
18746 }
18747 
18748 NK_API void
18749 nk_window_set_bounds(struct nk_context *ctx, struct nk_rect bounds)
18750 {
18751  NK_ASSERT(ctx); NK_ASSERT(ctx->current);
18752  if (!ctx || !ctx->current) return;
18753  ctx->current->bounds = bounds;
18754 }
18755 
18756 NK_API void
18757 nk_window_set_position(struct nk_context *ctx, struct nk_vec2 pos)
18758 {
18759  NK_ASSERT(ctx); NK_ASSERT(ctx->current);
18760  if (!ctx || !ctx->current) return;
18761  ctx->current->bounds.x = pos.x;
18762  ctx->current->bounds.y = pos.y;
18763 }
18764 
18765 NK_API void
18766 nk_window_set_size(struct nk_context *ctx, struct nk_vec2 size)
18767 {
18768  NK_ASSERT(ctx); NK_ASSERT(ctx->current);
18769  if (!ctx || !ctx->current) return;
18770  ctx->current->bounds.w = size.x;
18771  ctx->current->bounds.h = size.y;
18772 }
18773 
18774 NK_API void
18775 nk_window_collapse(struct nk_context *ctx, const char *name,
18776  enum nk_collapse_states c)
18777 {
18778  int title_len;
18779  nk_hash title_hash;
18780  struct nk_window *win;
18781  NK_ASSERT(ctx);
18782  if (!ctx) return;
18783 
18784  title_len = (int)nk_strlen(name);
18785  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18786  win = nk_find_window(ctx, title_hash, name);
18787  if (!win) return;
18788  if (c == NK_MINIMIZED)
18789  win->flags |= NK_WINDOW_MINIMIZED;
18790  else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
18791 }
18792 
18793 NK_API void
18794 nk_window_collapse_if(struct nk_context *ctx, const char *name,
18795  enum nk_collapse_states c, int cond)
18796 {
18797  NK_ASSERT(ctx);
18798  if (!ctx || !cond) return;
18799  nk_window_collapse(ctx, name, c);
18800 }
18801 
18802 NK_API void
18803 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
18804 {
18805  int title_len;
18806  nk_hash title_hash;
18807  struct nk_window *win;
18808  NK_ASSERT(ctx);
18809  if (!ctx) return;
18810 
18811  title_len = (int)nk_strlen(name);
18812  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18813  win = nk_find_window(ctx, title_hash, name);
18814  if (!win) return;
18815  if (s == NK_HIDDEN) {
18816  win->flags |= NK_WINDOW_HIDDEN;
18817  } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
18818 }
18819 
18820 NK_API void
18821 nk_window_show_if(struct nk_context *ctx, const char *name,
18822  enum nk_show_states s, int cond)
18823 {
18824  NK_ASSERT(ctx);
18825  if (!ctx || !cond) return;
18826  nk_window_show(ctx, name, s);
18827 }
18828 
18829 NK_API void
18830 nk_window_set_focus(struct nk_context *ctx, const char *name)
18831 {
18832  int title_len;
18833  nk_hash title_hash;
18834  struct nk_window *win;
18835  NK_ASSERT(ctx);
18836  if (!ctx) return;
18837 
18838  title_len = (int)nk_strlen(name);
18839  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18840  win = nk_find_window(ctx, title_hash, name);
18841  if (win && ctx->end != win) {
18842  nk_remove_window(ctx, win);
18843  nk_insert_window(ctx, win, NK_INSERT_BACK);
18844  }
18845  ctx->active = win;
18846 }
18847 
18848 /*----------------------------------------------------------------
18849  *
18850  * MENUBAR
18851  *
18852  * --------------------------------------------------------------*/
18853 NK_API void
18854 nk_menubar_begin(struct nk_context *ctx)
18855 {
18856  struct nk_panel *layout;
18857  NK_ASSERT(ctx);
18858  NK_ASSERT(ctx->current);
18859  NK_ASSERT(ctx->current->layout);
18860  if (!ctx || !ctx->current || !ctx->current->layout)
18861  return;
18862 
18863  layout = ctx->current->layout;
18864  NK_ASSERT(layout->at_y == layout->bounds.y);
18865  /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
18866  If you want a menubar the first nuklear function after `nk_begin` has to be a
18867  `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
18868  widgets (also supports multiple rows).
18869  Example:
18870  if (nk_begin(...)) {
18871  nk_menubar_begin(...);
18872  nk_layout_xxxx(...);
18873  nk_button(...);
18874  nk_layout_xxxx(...);
18875  nk_button(...);
18876  nk_menubar_end(...);
18877  }
18878  nk_end(...);
18879  */
18880  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
18881  return;
18882 
18883  layout->menu.x = layout->at_x;
18884  layout->menu.y = layout->at_y + layout->row.height;
18885  layout->menu.w = layout->bounds.w;
18886  layout->menu.offset.x = *layout->offset_x;
18887  layout->menu.offset.y = *layout->offset_y;
18888  *layout->offset_y = 0;
18889 }
18890 
18891 NK_API void
18892 nk_menubar_end(struct nk_context *ctx)
18893 {
18894  struct nk_window *win;
18895  struct nk_panel *layout;
18896  struct nk_command_buffer *out;
18897 
18898  NK_ASSERT(ctx);
18899  NK_ASSERT(ctx->current);
18900  NK_ASSERT(ctx->current->layout);
18901  if (!ctx || !ctx->current || !ctx->current->layout)
18902  return;
18903 
18904  win = ctx->current;
18905  out = &win->buffer;
18906  layout = win->layout;
18907  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
18908  return;
18909 
18910  layout->menu.h = layout->at_y - layout->menu.y;
18911  layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
18912  layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
18913 
18914  *layout->offset_x = layout->menu.offset.x;
18915  *layout->offset_y = layout->menu.offset.y;
18916  layout->at_y = layout->bounds.y - layout->row.height;
18917 
18918  layout->clip.y = layout->bounds.y;
18919  layout->clip.h = layout->bounds.h;
18920  nk_push_scissor(out, layout->clip);
18921 }
18922 /* -------------------------------------------------------------
18923  *
18924  * LAYOUT
18925  *
18926  * --------------------------------------------------------------*/
18927 NK_INTERN float
18928 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
18929  float total_space, int columns)
18930 {
18931  float panel_padding;
18932  float panel_spacing;
18933  float panel_space;
18934 
18935  struct nk_vec2 spacing;
18936  struct nk_vec2 padding;
18937 
18938  spacing = style->window.spacing;
18939  padding = nk_panel_get_padding(style, type);
18940 
18941  /* calculate the usable panel space */
18942  panel_padding = 2 * padding.x;
18943  panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
18944  panel_space = total_space - panel_padding - panel_spacing;
18945  return panel_space;
18946 }
18947 
18948 NK_INTERN void
18949 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
18950  float height, int cols)
18951 {
18952  struct nk_panel *layout;
18953  const struct nk_style *style;
18954  struct nk_command_buffer *out;
18955 
18956  struct nk_vec2 item_spacing;
18957  struct nk_color color;
18958 
18959  NK_ASSERT(ctx);
18960  NK_ASSERT(ctx->current);
18961  NK_ASSERT(ctx->current->layout);
18962  if (!ctx || !ctx->current || !ctx->current->layout)
18963  return;
18964 
18965  /* prefetch some configuration data */
18966  layout = win->layout;
18967  style = &ctx->style;
18968  out = &win->buffer;
18969  color = style->window.background;
18970  item_spacing = style->window.spacing;
18971 
18972  /* if one of these triggers you forgot to add an `if` condition around either
18973  a window, group, popup, combobox or contextual menu `begin` and `end` block.
18974  Example:
18975  if (nk_begin(...) {...} nk_end(...); or
18976  if (nk_group_begin(...) { nk_group_end(...);} */
18977  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
18978  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
18979  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
18980 
18981  /* update the current row and set the current row layout */
18982  layout->row.index = 0;
18983  layout->at_y += layout->row.height;
18984  layout->row.columns = cols;
18985  layout->row.height = height + item_spacing.y;
18986  layout->row.item_offset = 0;
18987  if (layout->flags & NK_WINDOW_DYNAMIC) {
18988  /* draw background for dynamic panels */
18989  struct nk_rect background;
18990  background.x = win->bounds.x;
18991  background.w = win->bounds.w;
18992  background.y = layout->at_y - 1.0f;
18993  background.h = layout->row.height + 1.0f;
18994  nk_fill_rect(out, background, 0, color);
18995  }
18996 }
18997 
18998 NK_INTERN void
18999 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
19000  float height, int cols, int width)
19001 {
19002  /* update the current row and set the current row layout */
19003  struct nk_window *win;
19004  NK_ASSERT(ctx);
19005  NK_ASSERT(ctx->current);
19006  NK_ASSERT(ctx->current->layout);
19007  if (!ctx || !ctx->current || !ctx->current->layout)
19008  return;
19009 
19010  win = ctx->current;
19011  nk_panel_layout(ctx, win, height, cols);
19012  if (fmt == NK_DYNAMIC)
19014  else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
19015 
19016  win->layout->row.ratio = 0;
19017  win->layout->row.filled = 0;
19018  win->layout->row.item_offset = 0;
19019  win->layout->row.item_width = (float)width;
19020 }
19021 
19022 NK_API float
19023 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
19024 {
19025  struct nk_window *win;
19026  NK_ASSERT(ctx);
19027  NK_ASSERT(pixel_width);
19028  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
19029  win = ctx->current;
19030  return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
19031 }
19032 
19033 NK_API void
19034 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
19035 {
19036  nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
19037 }
19038 
19039 NK_API void
19040 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
19041 {
19042  nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
19043 }
19044 
19045 NK_API void
19046 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
19047  float row_height, int cols)
19048 {
19049  struct nk_window *win;
19050  struct nk_panel *layout;
19051 
19052  NK_ASSERT(ctx);
19053  NK_ASSERT(ctx->current);
19054  NK_ASSERT(ctx->current->layout);
19055  if (!ctx || !ctx->current || !ctx->current->layout)
19056  return;
19057 
19058  win = ctx->current;
19059  layout = win->layout;
19060  nk_panel_layout(ctx, win, row_height, cols);
19061  if (fmt == NK_DYNAMIC)
19062  layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
19063  else layout->row.type = NK_LAYOUT_STATIC_ROW;
19064 
19065  layout->row.ratio = 0;
19066  layout->row.filled = 0;
19067  layout->row.item_width = 0;
19068  layout->row.item_offset = 0;
19069  layout->row.columns = cols;
19070 }
19071 
19072 NK_API void
19073 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
19074 {
19075  struct nk_window *win;
19076  struct nk_panel *layout;
19077 
19078  NK_ASSERT(ctx);
19079  NK_ASSERT(ctx->current);
19080  NK_ASSERT(ctx->current->layout);
19081  if (!ctx || !ctx->current || !ctx->current->layout)
19082  return;
19083 
19084  win = ctx->current;
19085  layout = win->layout;
19086  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
19087  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
19088  return;
19089 
19090  if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
19091  float ratio = ratio_or_width;
19092  if ((ratio + layout->row.filled) > 1.0f) return;
19093  if (ratio > 0.0f)
19094  layout->row.item_width = NK_SATURATE(ratio);
19095  else layout->row.item_width = 1.0f - layout->row.filled;
19096  } else layout->row.item_width = ratio_or_width;
19097 }
19098 
19099 NK_API void
19100 nk_layout_row_end(struct nk_context *ctx)
19101 {
19102  struct nk_window *win;
19103  struct nk_panel *layout;
19104 
19105  NK_ASSERT(ctx);
19106  NK_ASSERT(ctx->current);
19107  NK_ASSERT(ctx->current->layout);
19108  if (!ctx || !ctx->current || !ctx->current->layout)
19109  return;
19110 
19111  win = ctx->current;
19112  layout = win->layout;
19113  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
19114  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
19115  return;
19116  layout->row.item_width = 0;
19117  layout->row.item_offset = 0;
19118 }
19119 
19120 NK_API void
19121 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
19122  float height, int cols, const float *ratio)
19123 {
19124  int i;
19125  int n_undef = 0;
19126  struct nk_window *win;
19127  struct nk_panel *layout;
19128 
19129  NK_ASSERT(ctx);
19130  NK_ASSERT(ctx->current);
19131  NK_ASSERT(ctx->current->layout);
19132  if (!ctx || !ctx->current || !ctx->current->layout)
19133  return;
19134 
19135  win = ctx->current;
19136  layout = win->layout;
19137  nk_panel_layout(ctx, win, height, cols);
19138  if (fmt == NK_DYNAMIC) {
19139  /* calculate width of undefined widget ratios */
19140  float r = 0;
19141  layout->row.ratio = ratio;
19142  for (i = 0; i < cols; ++i) {
19143  if (ratio[i] < 0.0f)
19144  n_undef++;
19145  else r += ratio[i];
19146  }
19147  r = NK_SATURATE(1.0f - r);
19148  layout->row.type = NK_LAYOUT_DYNAMIC;
19149  layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
19150  } else {
19151  layout->row.ratio = ratio;
19152  layout->row.type = NK_LAYOUT_STATIC;
19153  layout->row.item_width = 0;
19154  layout->row.item_offset = 0;
19155  }
19156  layout->row.item_offset = 0;
19157  layout->row.filled = 0;
19158 }
19159 
19160 NK_API void
19161 nk_layout_row_template_begin(struct nk_context *ctx, float height)
19162 {
19163  struct nk_window *win;
19164  struct nk_panel *layout;
19165 
19166  NK_ASSERT(ctx);
19167  NK_ASSERT(ctx->current);
19168  NK_ASSERT(ctx->current->layout);
19169  if (!ctx || !ctx->current || !ctx->current->layout)
19170  return;
19171 
19172  win = ctx->current;
19173  layout = win->layout;
19174  nk_panel_layout(ctx, win, height, 1);
19175  layout->row.type = NK_LAYOUT_TEMPLATE;
19176  layout->row.columns = 0;
19177  layout->row.ratio = 0;
19178  layout->row.item_width = 0;
19179  layout->row.item_height = 0;
19180  layout->row.item_offset = 0;
19181  layout->row.filled = 0;
19182  layout->row.item.x = 0;
19183  layout->row.item.y = 0;
19184  layout->row.item.w = 0;
19185  layout->row.item.h = 0;
19186 }
19187 
19188 NK_API void
19190 {
19191  struct nk_window *win;
19192  struct nk_panel *layout;
19193 
19194  NK_ASSERT(ctx);
19195  NK_ASSERT(ctx->current);
19196  NK_ASSERT(ctx->current->layout);
19197  if (!ctx || !ctx->current || !ctx->current->layout)
19198  return;
19199 
19200  win = ctx->current;
19201  layout = win->layout;
19202  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19203  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19204  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19205  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19206  layout->row.templates[layout->row.columns++] = -1.0f;
19207 }
19208 
19209 NK_API void
19210 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
19211 {
19212  struct nk_window *win;
19213  struct nk_panel *layout;
19214 
19215  NK_ASSERT(ctx);
19216  NK_ASSERT(ctx->current);
19217  NK_ASSERT(ctx->current->layout);
19218  if (!ctx || !ctx->current || !ctx->current->layout)
19219  return;
19220 
19221  win = ctx->current;
19222  layout = win->layout;
19223  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19224  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19225  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19226  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19227  layout->row.templates[layout->row.columns++] = -min_width;
19228 }
19229 
19230 NK_API void
19231 nk_layout_row_template_push_static(struct nk_context *ctx, float width)
19232 {
19233  struct nk_window *win;
19234  struct nk_panel *layout;
19235 
19236  NK_ASSERT(ctx);
19237  NK_ASSERT(ctx->current);
19238  NK_ASSERT(ctx->current->layout);
19239  if (!ctx || !ctx->current || !ctx->current->layout)
19240  return;
19241 
19242  win = ctx->current;
19243  layout = win->layout;
19244  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19245  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19246  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19247  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19248  layout->row.templates[layout->row.columns++] = width;
19249 }
19250 
19251 NK_API void
19253 {
19254  struct nk_window *win;
19255  struct nk_panel *layout;
19256 
19257  int i = 0;
19258  int variable_count = 0;
19259  int min_variable_count = 0;
19260  float min_fixed_width = 0.0f;
19261  float total_fixed_width = 0.0f;
19262  float max_variable_width = 0.0f;
19263 
19264  NK_ASSERT(ctx);
19265  NK_ASSERT(ctx->current);
19266  NK_ASSERT(ctx->current->layout);
19267  if (!ctx || !ctx->current || !ctx->current->layout)
19268  return;
19269 
19270  win = ctx->current;
19271  layout = win->layout;
19272  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19273  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19274  for (i = 0; i < layout->row.columns; ++i) {
19275  float width = layout->row.templates[i];
19276  if (width >= 0.0f) {
19277  total_fixed_width += width;
19278  min_fixed_width += width;
19279  } else if (width < -1.0f) {
19280  width = -width;
19281  total_fixed_width += width;
19282  max_variable_width = NK_MAX(max_variable_width, width);
19283  variable_count++;
19284  } else {
19285  min_variable_count++;
19286  variable_count++;
19287  }
19288  }
19289  if (variable_count) {
19290  float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
19291  layout->bounds.w, layout->row.columns);
19292  float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
19293  int enough_space = var_width >= max_variable_width;
19294  if (!enough_space)
19295  var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
19296  for (i = 0; i < layout->row.columns; ++i) {
19297  float *width = &layout->row.templates[i];
19298  *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
19299  }
19300  }
19301 }
19302 
19303 NK_API void
19304 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
19305  float height, int widget_count)
19306 {
19307  struct nk_window *win;
19308  struct nk_panel *layout;
19309 
19310  NK_ASSERT(ctx);
19311  NK_ASSERT(ctx->current);
19312  NK_ASSERT(ctx->current->layout);
19313  if (!ctx || !ctx->current || !ctx->current->layout)
19314  return;
19315 
19316  win = ctx->current;
19317  layout = win->layout;
19318  nk_panel_layout(ctx, win, height, widget_count);
19319  if (fmt == NK_STATIC)
19320  layout->row.type = NK_LAYOUT_STATIC_FREE;
19321  else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
19322 
19323  layout->row.ratio = 0;
19324  layout->row.filled = 0;
19325  layout->row.item_width = 0;
19326  layout->row.item_offset = 0;
19327 }
19328 
19329 NK_API void
19330 nk_layout_space_end(struct nk_context *ctx)
19331 {
19332  struct nk_window *win;
19333  struct nk_panel *layout;
19334 
19335  NK_ASSERT(ctx);
19336  NK_ASSERT(ctx->current);
19337  NK_ASSERT(ctx->current->layout);
19338  if (!ctx || !ctx->current || !ctx->current->layout)
19339  return;
19340 
19341  win = ctx->current;
19342  layout = win->layout;
19343  layout->row.item_width = 0;
19344  layout->row.item_height = 0;
19345  layout->row.item_offset = 0;
19346  nk_zero(&layout->row.item, sizeof(layout->row.item));
19347 }
19348 
19349 NK_API void
19350 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
19351 {
19352  struct nk_window *win;
19353  struct nk_panel *layout;
19354 
19355  NK_ASSERT(ctx);
19356  NK_ASSERT(ctx->current);
19357  NK_ASSERT(ctx->current->layout);
19358  if (!ctx || !ctx->current || !ctx->current->layout)
19359  return;
19360 
19361  win = ctx->current;
19362  layout = win->layout;
19363  layout->row.item = rect;
19364 }
19365 
19366 NK_API struct nk_rect
19368 {
19369  struct nk_rect ret;
19370  struct nk_window *win;
19371  struct nk_panel *layout;
19372 
19373  NK_ASSERT(ctx);
19374  NK_ASSERT(ctx->current);
19375  NK_ASSERT(ctx->current->layout);
19376  win = ctx->current;
19377  layout = win->layout;
19378 
19379  ret.x = layout->clip.x;
19380  ret.y = layout->clip.y;
19381  ret.w = layout->clip.w;
19382  ret.h = layout->row.height;
19383  return ret;
19384 }
19385 
19386 NK_API struct nk_vec2
19387 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
19388 {
19389  struct nk_window *win;
19390  struct nk_panel *layout;
19391 
19392  NK_ASSERT(ctx);
19393  NK_ASSERT(ctx->current);
19394  NK_ASSERT(ctx->current->layout);
19395  win = ctx->current;
19396  layout = win->layout;
19397 
19398  ret.x += layout->at_x - (float)*layout->offset_x;
19399  ret.y += layout->at_y - (float)*layout->offset_y;
19400  return ret;
19401 }
19402 
19403 NK_API struct nk_vec2
19404 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
19405 {
19406  struct nk_window *win;
19407  struct nk_panel *layout;
19408 
19409  NK_ASSERT(ctx);
19410  NK_ASSERT(ctx->current);
19411  NK_ASSERT(ctx->current->layout);
19412  win = ctx->current;
19413  layout = win->layout;
19414 
19415  ret.x += -layout->at_x + (float)*layout->offset_x;
19416  ret.y += -layout->at_y + (float)*layout->offset_y;
19417  return ret;
19418 }
19419 
19420 NK_API struct nk_rect
19422 {
19423  struct nk_window *win;
19424  struct nk_panel *layout;
19425 
19426  NK_ASSERT(ctx);
19427  NK_ASSERT(ctx->current);
19428  NK_ASSERT(ctx->current->layout);
19429  win = ctx->current;
19430  layout = win->layout;
19431 
19432  ret.x += layout->at_x - (float)*layout->offset_x;
19433  ret.y += layout->at_y - (float)*layout->offset_y;
19434  return ret;
19435 }
19436 
19437 NK_API struct nk_rect
19439 {
19440  struct nk_window *win;
19441  struct nk_panel *layout;
19442 
19443  NK_ASSERT(ctx);
19444  NK_ASSERT(ctx->current);
19445  NK_ASSERT(ctx->current->layout);
19446  win = ctx->current;
19447  layout = win->layout;
19448 
19449  ret.x += -layout->at_x + (float)*layout->offset_x;
19450  ret.y += -layout->at_y + (float)*layout->offset_y;
19451  return ret;
19452 }
19453 
19454 NK_INTERN void
19455 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
19456 {
19457  struct nk_panel *layout = win->layout;
19458  struct nk_vec2 spacing = ctx->style.window.spacing;
19459  const float row_height = layout->row.height - spacing.y;
19460  nk_panel_layout(ctx, win, row_height, layout->row.columns);
19461 }
19462 
19463 NK_INTERN void
19464 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
19465  struct nk_window *win, int modify)
19466 {
19467  struct nk_panel *layout;
19468  const struct nk_style *style;
19469 
19470  struct nk_vec2 spacing;
19471  struct nk_vec2 padding;
19472 
19473  float item_offset = 0;
19474  float item_width = 0;
19475  float item_spacing = 0;
19476  float panel_space = 0;
19477 
19478  NK_ASSERT(ctx);
19479  NK_ASSERT(ctx->current);
19480  NK_ASSERT(ctx->current->layout);
19481  if (!ctx || !ctx->current || !ctx->current->layout)
19482  return;
19483 
19484  win = ctx->current;
19485  layout = win->layout;
19486  style = &ctx->style;
19487  NK_ASSERT(bounds);
19488 
19489  spacing = style->window.spacing;
19490  padding = nk_panel_get_padding(style, layout->type);
19491  panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
19492  layout->bounds.w, layout->row.columns);
19493 
19494  /* calculate the width of one item inside the current layout space */
19495  switch (layout->row.type) {
19496  case NK_LAYOUT_DYNAMIC_FIXED: {
19497  /* scaling fixed size widgets item width */
19498  item_width = NK_MAX(1.0f,panel_space-1.0f) / (float)layout->row.columns;
19499  item_offset = (float)layout->row.index * item_width;
19500  item_spacing = (float)layout->row.index * spacing.x;
19501  } break;
19502  case NK_LAYOUT_DYNAMIC_ROW: {
19503  /* scaling single ratio widget width */
19504  item_width = layout->row.item_width * panel_space;
19505  item_offset = layout->row.item_offset;
19506  item_spacing = 0;
19507 
19508  if (modify) {
19509  layout->row.item_offset += item_width + spacing.x;
19510  layout->row.filled += layout->row.item_width;
19511  layout->row.index = 0;
19512  }
19513  } break;
19514  case NK_LAYOUT_DYNAMIC_FREE: {
19515  /* panel width depended free widget placing */
19516  bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
19517  bounds->x -= (float)*layout->offset_x;
19518  bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
19519  bounds->y -= (float)*layout->offset_y;
19520  bounds->w = layout->bounds.w * layout->row.item.w;
19521  bounds->h = layout->row.height * layout->row.item.h;
19522  return;
19523  } break;
19524  case NK_LAYOUT_DYNAMIC: {
19525  /* scaling arrays of panel width ratios for every widget */
19526  float ratio;
19527  NK_ASSERT(layout->row.ratio);
19528  ratio = (layout->row.ratio[layout->row.index] < 0) ?
19529  layout->row.item_width : layout->row.ratio[layout->row.index];
19530 
19531  item_spacing = (float)layout->row.index * spacing.x;
19532  item_width = (ratio * panel_space);
19533  item_offset = layout->row.item_offset;
19534 
19535  if (modify) {
19536  layout->row.item_offset += item_width;
19537  layout->row.filled += ratio;
19538  }
19539  } break;
19540  case NK_LAYOUT_STATIC_FIXED: {
19541  /* non-scaling fixed widgets item width */
19542  item_width = layout->row.item_width;
19543  item_offset = (float)layout->row.index * item_width;
19544  item_spacing = (float)layout->row.index * spacing.x;
19545  } break;
19546  case NK_LAYOUT_STATIC_ROW: {
19547  /* scaling single ratio widget width */
19548  item_width = layout->row.item_width;
19549  item_offset = layout->row.item_offset;
19550  item_spacing = (float)layout->row.index * spacing.x;
19551  if (modify) layout->row.item_offset += item_width;
19552  } break;
19553  case NK_LAYOUT_STATIC_FREE: {
19554  /* free widget placing */
19555  bounds->x = layout->at_x + layout->row.item.x;
19556  bounds->w = layout->row.item.w;
19557  if (((bounds->x + bounds->w) > layout->max_x) && modify)
19558  layout->max_x = (bounds->x + bounds->w);
19559  bounds->x -= (float)*layout->offset_x;
19560  bounds->y = layout->at_y + layout->row.item.y;
19561  bounds->y -= (float)*layout->offset_y;
19562  bounds->h = layout->row.item.h;
19563  return;
19564  } break;
19565  case NK_LAYOUT_STATIC: {
19566  /* non-scaling array of panel pixel width for every widget */
19567  item_spacing = (float)layout->row.index * spacing.x;
19568  item_width = layout->row.ratio[layout->row.index];
19569  item_offset = layout->row.item_offset;
19570  if (modify) layout->row.item_offset += item_width;
19571  } break;
19572  case NK_LAYOUT_TEMPLATE: {
19573  /* stretchy row layout with combined dynamic/static widget width*/
19574  NK_ASSERT(layout->row.index < layout->row.columns);
19575  NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19576  item_width = layout->row.templates[layout->row.index];
19577  item_offset = layout->row.item_offset;
19578  item_spacing = (float)layout->row.index * spacing.x;
19579  if (modify) layout->row.item_offset += item_width;
19580  } break;
19581  default: NK_ASSERT(0); break;
19582  };
19583 
19584  /* set the bounds of the newly allocated widget */
19585  bounds->w = item_width;
19586  bounds->h = layout->row.height - spacing.y;
19587  bounds->y = layout->at_y - (float)*layout->offset_y;
19588  bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
19589  if (((bounds->x + bounds->w) > layout->max_x) && modify)
19590  layout->max_x = bounds->x + bounds->w;
19591  bounds->x -= (float)*layout->offset_x;
19592 }
19593 
19594 NK_INTERN void
19595 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
19596 {
19597  struct nk_window *win;
19598  struct nk_panel *layout;
19599 
19600  NK_ASSERT(ctx);
19601  NK_ASSERT(ctx->current);
19602  NK_ASSERT(ctx->current->layout);
19603  if (!ctx || !ctx->current || !ctx->current->layout)
19604  return;
19605 
19606  /* check if the end of the row has been hit and begin new row if so */
19607  win = ctx->current;
19608  layout = win->layout;
19609  if (layout->row.index >= layout->row.columns)
19610  nk_panel_alloc_row(ctx, win);
19611 
19612  /* calculate widget position and size */
19613  nk_layout_widget_space(bounds, ctx, win, nk_true);
19614  layout->row.index++;
19615 }
19616 
19617 NK_INTERN void
19618 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
19619 {
19620  float y;
19621  int index;
19622  struct nk_window *win;
19623  struct nk_panel *layout;
19624 
19625  NK_ASSERT(ctx);
19626  NK_ASSERT(ctx->current);
19627  NK_ASSERT(ctx->current->layout);
19628  if (!ctx || !ctx->current || !ctx->current->layout)
19629  return;
19630 
19631  win = ctx->current;
19632  layout = win->layout;
19633  y = layout->at_y;
19634  index = layout->row.index;
19635  if (layout->row.index >= layout->row.columns) {
19636  layout->at_y += layout->row.height;
19637  layout->row.index = 0;
19638  }
19639  nk_layout_widget_space(bounds, ctx, win, nk_false);
19640  layout->at_y = y;
19641  layout->row.index = index;
19642 }
19643 
19644 NK_INTERN int
19645 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
19646  struct nk_image *img, const char *title, enum nk_collapse_states *state)
19647 {
19648  struct nk_window *win;
19649  struct nk_panel *layout;
19650  const struct nk_style *style;
19651  struct nk_command_buffer *out;
19652  const struct nk_input *in;
19653  const struct nk_style_button *button;
19654  enum nk_symbol_type symbol;
19655 
19656  struct nk_vec2 item_spacing;
19657  struct nk_rect header = {0,0,0,0};
19658  struct nk_rect sym = {0,0,0,0};
19659  struct nk_text text;
19660 
19661  nk_flags ws = 0;
19662  enum nk_widget_layout_states widget_state;
19663 
19664  NK_ASSERT(ctx);
19665  NK_ASSERT(ctx->current);
19666  NK_ASSERT(ctx->current->layout);
19667  if (!ctx || !ctx->current || !ctx->current->layout)
19668  return 0;
19669 
19670  /* cache some data */
19671  win = ctx->current;
19672  layout = win->layout;
19673  out = &win->buffer;
19674  style = &ctx->style;
19675  item_spacing = style->window.spacing;
19676 
19677  /* calculate header bounds and draw background */
19678  nk_layout_row_dynamic(ctx, style->font->height + 2 * style->tab.padding.y, 1);
19679  widget_state = nk_widget(&header, ctx);
19680  if (type == NK_TREE_TAB) {
19681  const struct nk_style_item *background = &style->tab.background;
19682  if (background->type == NK_STYLE_ITEM_IMAGE) {
19683  nk_draw_image(out, header, &background->data.image, nk_white);
19684  text.background = nk_rgba(0,0,0,0);
19685  } else {
19686  text.background = background->data.color;
19687  nk_fill_rect(out, header, 0, style->tab.border_color);
19688  nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
19689  style->tab.rounding, background->data.color);
19690  }
19691  } else text.background = style->window.background;
19692 
19693  /* update node state */
19694  in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
19695  in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
19696  if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
19697  *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
19698 
19699  /* select correct button style */
19700  if (*state == NK_MAXIMIZED) {
19701  symbol = style->tab.sym_maximize;
19702  if (type == NK_TREE_TAB)
19703  button = &style->tab.tab_maximize_button;
19704  else button = &style->tab.node_maximize_button;
19705  } else {
19706  symbol = style->tab.sym_minimize;
19707  if (type == NK_TREE_TAB)
19708  button = &style->tab.tab_minimize_button;
19709  else button = &style->tab.node_minimize_button;
19710  }
19711 
19712  {/* draw triangle button */
19713  sym.w = sym.h = style->font->height;
19714  sym.y = header.y + style->tab.padding.y;
19715  sym.x = header.x + style->tab.padding.x;
19716  nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
19717  button, 0, style->font);
19718 
19719  if (img) {
19720  /* draw optional image icon */
19721  sym.x = sym.x + sym.w + 4 * item_spacing.x;
19722  nk_draw_image(&win->buffer, sym, img, nk_white);
19723  sym.w = style->font->height + style->tab.spacing.x;}
19724  }
19725 
19726  {/* draw label */
19727  struct nk_rect label;
19728  header.w = NK_MAX(header.w, sym.w + item_spacing.x);
19729  label.x = sym.x + sym.w + item_spacing.x;
19730  label.y = sym.y;
19731  label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
19732  label.h = style->font->height;
19733  text.text = style->tab.text;
19734  text.padding = nk_vec2(0,0);
19735  nk_widget_text(out, label, title, nk_strlen(title), &text,
19736  NK_TEXT_LEFT, style->font);}
19737 
19738  /* increase x-axis cursor widget position pointer */
19739  if (*state == NK_MAXIMIZED) {
19740  layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
19741  layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
19742  layout->bounds.w -= (style->tab.indent + style->window.padding.x);
19743  layout->row.tree_depth++;
19744  return nk_true;
19745  } else return nk_false;
19746 }
19747 
19748 NK_INTERN int
19749 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
19750  struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
19751  const char *hash, int len, int line)
19752 {
19753  struct nk_window *win = ctx->current;
19754  int title_len = 0;
19755  nk_hash tree_hash = 0;
19756  nk_uint *state = 0;
19757 
19758  /* retrieve tree state from internal widget state tables */
19759  if (!hash) {
19760  title_len = (int)nk_strlen(title);
19761  tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
19762  } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
19763  state = nk_find_value(win, tree_hash);
19764  if (!state) {
19765  state = nk_add_value(ctx, win, tree_hash, 0);
19766  *state = initial_state;
19767  }
19768  return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
19769 }
19770 
19771 NK_API int
19772 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
19773  const char *title, enum nk_collapse_states *state)
19774 {return nk_tree_state_base(ctx, type, 0, title, state);}
19775 
19776 NK_API int
19777 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
19778  struct nk_image img, const char *title, enum nk_collapse_states *state)
19779 {return nk_tree_state_base(ctx, type, &img, title, state);}
19780 
19781 NK_API void
19782 nk_tree_state_pop(struct nk_context *ctx)
19783 {
19784  struct nk_window *win = 0;
19785  struct nk_panel *layout = 0;
19786 
19787  NK_ASSERT(ctx);
19788  NK_ASSERT(ctx->current);
19789  NK_ASSERT(ctx->current->layout);
19790  if (!ctx || !ctx->current || !ctx->current->layout)
19791  return;
19792 
19793  win = ctx->current;
19794  layout = win->layout;
19795  layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x;
19796  layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
19797  NK_ASSERT(layout->row.tree_depth);
19798  layout->row.tree_depth--;
19799 }
19800 
19801 NK_API int
19802 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
19803  const char *title, enum nk_collapse_states initial_state,
19804  const char *hash, int len, int line)
19805 {return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);}
19806 
19807 NK_API int
19808 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
19809  struct nk_image img, const char *title, enum nk_collapse_states initial_state,
19810  const char *hash, int len,int seed)
19811 {return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);}
19812 
19813 NK_API void
19814 nk_tree_pop(struct nk_context *ctx)
19815 {nk_tree_state_pop(ctx);}
19816 
19817 /*----------------------------------------------------------------
19818  *
19819  * WIDGETS
19820  *
19821  * --------------------------------------------------------------*/
19822 NK_API struct nk_rect
19824 {
19825  struct nk_rect bounds;
19826  NK_ASSERT(ctx);
19827  NK_ASSERT(ctx->current);
19828  if (!ctx || !ctx->current)
19829  return nk_rect(0,0,0,0);
19830  nk_layout_peek(&bounds, ctx);
19831  return bounds;
19832 }
19833 
19834 NK_API struct nk_vec2
19836 {
19837  struct nk_rect bounds;
19838  NK_ASSERT(ctx);
19839  NK_ASSERT(ctx->current);
19840  if (!ctx || !ctx->current)
19841  return nk_vec2(0,0);
19842 
19843  nk_layout_peek(&bounds, ctx);
19844  return nk_vec2(bounds.x, bounds.y);
19845 }
19846 
19847 NK_API struct nk_vec2
19848 nk_widget_size(struct nk_context *ctx)
19849 {
19850  struct nk_rect bounds;
19851  NK_ASSERT(ctx);
19852  NK_ASSERT(ctx->current);
19853  if (!ctx || !ctx->current)
19854  return nk_vec2(0,0);
19855 
19856  nk_layout_peek(&bounds, ctx);
19857  return nk_vec2(bounds.w, bounds.h);
19858 }
19859 
19860 NK_API float
19861 nk_widget_width(struct nk_context *ctx)
19862 {
19863  struct nk_rect bounds;
19864  NK_ASSERT(ctx);
19865  NK_ASSERT(ctx->current);
19866  if (!ctx || !ctx->current)
19867  return 0;
19868 
19869  nk_layout_peek(&bounds, ctx);
19870  return bounds.w;
19871 }
19872 
19873 NK_API float
19874 nk_widget_height(struct nk_context *ctx)
19875 {
19876  struct nk_rect bounds;
19877  NK_ASSERT(ctx);
19878  NK_ASSERT(ctx->current);
19879  if (!ctx || !ctx->current)
19880  return 0;
19881 
19882  nk_layout_peek(&bounds, ctx);
19883  return bounds.h;
19884 }
19885 
19886 NK_API int
19887 nk_widget_is_hovered(struct nk_context *ctx)
19888 {
19889  int ret;
19890  struct nk_rect bounds;
19891  NK_ASSERT(ctx);
19892  NK_ASSERT(ctx->current);
19893  if (!ctx || !ctx->current)
19894  return 0;
19895 
19896  nk_layout_peek(&bounds, ctx);
19897  ret = (ctx->active == ctx->current);
19898  ret = ret && nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
19899  return ret;
19900 }
19901 
19902 NK_API int
19903 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn)
19904 {
19905  int ret;
19906  struct nk_rect bounds;
19907  NK_ASSERT(ctx);
19908  NK_ASSERT(ctx->current);
19909  if (!ctx || !ctx->current)
19910  return 0;
19911 
19912  nk_layout_peek(&bounds, ctx);
19913  ret = (ctx->active == ctx->current);
19914  ret = ret && nk_input_mouse_clicked(&ctx->input, btn, bounds);
19915  return ret;
19916 }
19917 
19918 NK_API int
19919 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down)
19920 {
19921  int ret;
19922  struct nk_rect bounds;
19923  NK_ASSERT(ctx);
19924  NK_ASSERT(ctx->current);
19925  if (!ctx || !ctx->current)
19926  return 0;
19927 
19928  nk_layout_peek(&bounds, ctx);
19929  ret = (ctx->active == ctx->current);
19930  ret = ret && nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
19931  return ret;
19932 }
19933 
19935 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
19936 {
19937  struct nk_rect c;
19938  struct nk_window *win;
19939  struct nk_panel *layout;
19940 
19941  NK_ASSERT(ctx);
19942  NK_ASSERT(ctx->current);
19943  NK_ASSERT(ctx->current->layout);
19944  if (!ctx || !ctx->current || !ctx->current->layout)
19945  return NK_WIDGET_INVALID;
19946 
19947  /* allocate space and check if the widget needs to be updated and drawn */
19948  nk_panel_alloc_space(bounds, ctx);
19949  win = ctx->current;
19950  layout = win->layout;
19951  c = layout->clip;
19952 
19953  /* if one of these triggers you forgot to add an `if` condition around either
19954  a window, group, popup, combobox or contextual menu `begin` and `end` block.
19955  Example:
19956  if (nk_begin(...) {...} nk_end(...); or
19957  if (nk_group_begin(...) { nk_group_end(...);} */
19958  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
19959  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
19960  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
19961 
19962  /* need to convert to int here to remove floating point errors */
19963  bounds->x = (float)((int)bounds->x);
19964  bounds->y = (float)((int)bounds->y);
19965  bounds->w = (float)((int)bounds->w);
19966  bounds->h = (float)((int)bounds->h);
19967 
19968  c.x = (float)((int)c.x);
19969  c.y = (float)((int)c.y);
19970  c.w = (float)((int)c.w);
19971  c.h = (float)((int)c.h);
19972 
19973  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
19974  return NK_WIDGET_INVALID;
19975  if (!NK_CONTAINS(bounds->x, bounds->y, bounds->w, bounds->h, c.x, c.y, c.w, c.h))
19976  return NK_WIDGET_ROM;
19977  return NK_WIDGET_VALID;
19978 }
19979 
19981 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
19982  struct nk_vec2 item_padding)
19983 {
19984  /* update the bounds to stand without padding */
19985  struct nk_window *win;
19986  struct nk_style *style;
19987  struct nk_panel *layout;
19988  enum nk_widget_layout_states state;
19989  struct nk_vec2 panel_padding;
19990 
19991  NK_ASSERT(ctx);
19992  NK_ASSERT(ctx->current);
19993  NK_ASSERT(ctx->current->layout);
19994  if (!ctx || !ctx->current || !ctx->current->layout)
19995  return NK_WIDGET_INVALID;
19996 
19997  win = ctx->current;
19998  style = &ctx->style;
19999  layout = win->layout;
20000  state = nk_widget(bounds, ctx);
20001 
20002  panel_padding = nk_panel_get_padding(style, layout->type);
20003  if (layout->row.index == 1) {
20004  bounds->w += panel_padding.x;
20005  bounds->x -= panel_padding.x;
20006  } else bounds->x -= item_padding.x;
20007 
20008  if (layout->row.index == layout->row.columns)
20009  bounds->w += panel_padding.x;
20010  else bounds->w += item_padding.x;
20011  return state;
20012 }
20013 
20014 /*----------------------------------------------------------------
20015  *
20016  * MISC
20017  *
20018  * --------------------------------------------------------------*/
20019 NK_API void
20020 nk_spacing(struct nk_context *ctx, int cols)
20021 {
20022  struct nk_window *win;
20023  struct nk_panel *layout;
20024  struct nk_rect none;
20025  int i, index, rows;
20026 
20027  NK_ASSERT(ctx);
20028  NK_ASSERT(ctx->current);
20029  NK_ASSERT(ctx->current->layout);
20030  if (!ctx || !ctx->current || !ctx->current->layout)
20031  return;
20032 
20033  /* spacing over row boundaries */
20034  win = ctx->current;
20035  layout = win->layout;
20036  index = (layout->row.index + cols) % layout->row.columns;
20037  rows = (layout->row.index + cols) / layout->row.columns;
20038  if (rows) {
20039  for (i = 0; i < rows; ++i)
20040  nk_panel_alloc_row(ctx, win);
20041  cols = index;
20042  }
20043 
20044  /* non table layout need to allocate space */
20045  if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
20046  layout->row.type != NK_LAYOUT_STATIC_FIXED) {
20047  for (i = 0; i < cols; ++i)
20048  nk_panel_alloc_space(&none, ctx);
20049  }
20050  layout->row.index = index;
20051 }
20052 
20053 /*----------------------------------------------------------------
20054  *
20055  * TEXT
20056  *
20057  * --------------------------------------------------------------*/
20058 NK_API void
20059 nk_text_colored(struct nk_context *ctx, const char *str, int len,
20060  nk_flags alignment, struct nk_color color)
20061 {
20062  struct nk_window *win;
20063  const struct nk_style *style;
20064 
20065  struct nk_vec2 item_padding;
20066  struct nk_rect bounds;
20067  struct nk_text text;
20068 
20069  NK_ASSERT(ctx);
20070  NK_ASSERT(ctx->current);
20071  NK_ASSERT(ctx->current->layout);
20072  if (!ctx || !ctx->current || !ctx->current->layout) return;
20073 
20074  win = ctx->current;
20075  style = &ctx->style;
20076  nk_panel_alloc_space(&bounds, ctx);
20077  item_padding = style->text.padding;
20078 
20079  text.padding.x = item_padding.x;
20080  text.padding.y = item_padding.y;
20081  text.background = style->window.background;
20082  text.text = color;
20083  nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
20084 }
20085 
20086 NK_API void
20087 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
20088  int len, struct nk_color color)
20089 {
20090  struct nk_window *win;
20091  const struct nk_style *style;
20092 
20093  struct nk_vec2 item_padding;
20094  struct nk_rect bounds;
20095  struct nk_text text;
20096 
20097  NK_ASSERT(ctx);
20098  NK_ASSERT(ctx->current);
20099  NK_ASSERT(ctx->current->layout);
20100  if (!ctx || !ctx->current || !ctx->current->layout) return;
20101 
20102  win = ctx->current;
20103  style = &ctx->style;
20104  nk_panel_alloc_space(&bounds, ctx);
20105  item_padding = style->text.padding;
20106 
20107  text.padding.x = item_padding.x;
20108  text.padding.y = item_padding.y;
20109  text.background = style->window.background;
20110  text.text = color;
20111  nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
20112 }
20113 
20114 #ifdef NK_INCLUDE_STANDARD_VARARGS
20115 NK_API void
20116 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
20117  struct nk_color color, const char *fmt, ...)
20118 {
20119  char buf[256];
20120  va_list args;
20121  va_start(args, fmt);
20122  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20123  nk_label_colored(ctx, buf, flags, color);
20124  va_end(args);
20125 }
20126 
20127 NK_API void
20128 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
20129  const char *fmt, ...)
20130 {
20131  char buf[256];
20132  va_list args;
20133  va_start(args, fmt);
20134  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20135  nk_label_colored_wrap(ctx, buf, color);
20136  va_end(args);
20137 }
20138 
20139 NK_API void
20140 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
20141 {
20142  char buf[256];
20143  va_list args;
20144  va_start(args, fmt);
20145  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20146  nk_label(ctx, buf, flags);
20147  va_end(args);
20148 }
20149 
20150 NK_API void
20151 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
20152 {
20153  char buf[256];
20154  va_list args;
20155  va_start(args, fmt);
20156  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20157  nk_label_wrap(ctx, buf);
20158  va_end(args);
20159 }
20160 
20161 NK_API void
20162 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
20163 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));}
20164 
20165 NK_API void
20166 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
20167 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);}
20168 
20169 NK_API void
20170 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
20171 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);}
20172 
20173 NK_API void
20174 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
20175 {
20176  double double_value = (double)value;
20177  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
20178 }
20179 
20180 NK_API void
20181 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
20182 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);}
20183 
20184 NK_API void
20185 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
20186 {
20187  double c[4]; nk_color_dv(c, color);
20188  nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
20189  p, c[0], c[1], c[2], c[3]);
20190 }
20191 
20192 NK_API void
20193 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
20194 {
20195  char hex[16];
20196  nk_color_hex_rgba(hex, color);
20197  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
20198 }
20199 #endif
20200 
20201 NK_API void
20202 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
20203 {
20204  NK_ASSERT(ctx);
20205  if (!ctx) return;
20206  nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
20207 }
20208 
20209 NK_API void
20210 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
20211 {
20212  NK_ASSERT(ctx);
20213  if (!ctx) return;
20214  nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
20215 }
20216 
20217 NK_API void
20218 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
20219 {nk_text(ctx, str, nk_strlen(str), alignment);}
20220 
20221 NK_API void
20222 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
20223  struct nk_color color)
20224 {nk_text_colored(ctx, str, nk_strlen(str), align, color);}
20225 
20226 NK_API void
20227 nk_label_wrap(struct nk_context *ctx, const char *str)
20228 {nk_text_wrap(ctx, str, nk_strlen(str));}
20229 
20230 NK_API void
20231 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
20232 {nk_text_wrap_colored(ctx, str, nk_strlen(str), color);}
20233 
20234 NK_API void
20235 nk_image(struct nk_context *ctx, struct nk_image img)
20236 {
20237  struct nk_window *win;
20238  struct nk_rect bounds;
20239 
20240  NK_ASSERT(ctx);
20241  NK_ASSERT(ctx->current);
20242  NK_ASSERT(ctx->current->layout);
20243  if (!ctx || !ctx->current || !ctx->current->layout) return;
20244 
20245  win = ctx->current;
20246  if (!nk_widget(&bounds, ctx)) return;
20247  nk_draw_image(&win->buffer, bounds, &img, nk_white);
20248 }
20249 
20250 /*----------------------------------------------------------------
20251  *
20252  * BUTTON
20253  *
20254  * --------------------------------------------------------------*/
20255 NK_API void
20256 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
20257 {
20258  NK_ASSERT(ctx);
20259  if (!ctx) return;
20260  ctx->button_behavior = behavior;
20261 }
20262 
20263 NK_API int
20264 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
20265 {
20266  struct nk_config_stack_button_behavior *button_stack;
20267  struct nk_config_stack_button_behavior_element *element;
20268 
20269  NK_ASSERT(ctx);
20270  if (!ctx) return 0;
20271 
20272  button_stack = &ctx->stacks.button_behaviors;
20273  NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
20274  if (button_stack->head >= (int)NK_LEN(button_stack->elements))
20275  return 0;
20276 
20277  element = &button_stack->elements[button_stack->head++];
20278  element->address = &ctx->button_behavior;
20279  element->old_value = ctx->button_behavior;
20280  ctx->button_behavior = behavior;
20281  return 1;
20282 }
20283 
20284 NK_API int
20286 {
20287  struct nk_config_stack_button_behavior *button_stack;
20288  struct nk_config_stack_button_behavior_element *element;
20289 
20290  NK_ASSERT(ctx);
20291  if (!ctx) return 0;
20292 
20293  button_stack = &ctx->stacks.button_behaviors;
20294  NK_ASSERT(button_stack->head > 0);
20295  if (button_stack->head < 1)
20296  return 0;
20297 
20298  element = &button_stack->elements[--button_stack->head];
20299  *element->address = element->old_value;
20300  return 1;
20301 }
20302 
20303 NK_API int
20304 nk_button_text_styled(struct nk_context *ctx,
20305  const struct nk_style_button *style, const char *title, int len)
20306 {
20307  struct nk_window *win;
20308  struct nk_panel *layout;
20309  const struct nk_input *in;
20310 
20311  struct nk_rect bounds;
20312  enum nk_widget_layout_states state;
20313 
20314  NK_ASSERT(ctx);
20315  NK_ASSERT(style);
20316  NK_ASSERT(ctx->current);
20317  NK_ASSERT(ctx->current->layout);
20318  if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
20319 
20320  win = ctx->current;
20321  layout = win->layout;
20322  state = nk_widget(&bounds, ctx);
20323 
20324  if (!state) return 0;
20325  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20326  return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
20327  title, len, style->text_alignment, ctx->button_behavior,
20328  style, in, ctx->style.font);
20329 }
20330 
20331 NK_API int
20332 nk_button_text(struct nk_context *ctx, const char *title, int len)
20333 {
20334  NK_ASSERT(ctx);
20335  if (!ctx) return 0;
20336  return nk_button_text_styled(ctx, &ctx->style.button, title, len);
20337 }
20338 
20339 NK_API int nk_button_label_styled(struct nk_context *ctx,
20340  const struct nk_style_button *style, const char *title)
20341 {return nk_button_text_styled(ctx, style, title, nk_strlen(title));}
20342 
20343 NK_API int nk_button_label(struct nk_context *ctx, const char *title)
20344 {return nk_button_text(ctx, title, nk_strlen(title));}
20345 
20346 NK_API int
20347 nk_button_color(struct nk_context *ctx, struct nk_color color)
20348 {
20349  struct nk_window *win;
20350  struct nk_panel *layout;
20351  const struct nk_input *in;
20352  struct nk_style_button button;
20353 
20354  int ret = 0;
20355  struct nk_rect bounds;
20356  struct nk_rect content;
20357  enum nk_widget_layout_states state;
20358 
20359  NK_ASSERT(ctx);
20360  NK_ASSERT(ctx->current);
20361  NK_ASSERT(ctx->current->layout);
20362  if (!ctx || !ctx->current || !ctx->current->layout)
20363  return 0;
20364 
20365  win = ctx->current;
20366  layout = win->layout;
20367 
20368  state = nk_widget(&bounds, ctx);
20369  if (!state) return 0;
20370  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20371 
20372  button = ctx->style.button;
20373  button.normal = nk_style_item_color(color);
20374  button.hover = nk_style_item_color(color);
20375  button.active = nk_style_item_color(color);
20376  ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
20377  &button, in, ctx->button_behavior, &content);
20378  nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
20379  return ret;
20380 }
20381 
20382 NK_API int
20384  const struct nk_style_button *style, enum nk_symbol_type symbol)
20385 {
20386  struct nk_window *win;
20387  struct nk_panel *layout;
20388  const struct nk_input *in;
20389 
20390  struct nk_rect bounds;
20391  enum nk_widget_layout_states state;
20392 
20393  NK_ASSERT(ctx);
20394  NK_ASSERT(ctx->current);
20395  NK_ASSERT(ctx->current->layout);
20396  if (!ctx || !ctx->current || !ctx->current->layout)
20397  return 0;
20398 
20399  win = ctx->current;
20400  layout = win->layout;
20401  state = nk_widget(&bounds, ctx);
20402  if (!state) return 0;
20403  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20404  return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20405  symbol, ctx->button_behavior, style, in, ctx->style.font);
20406 }
20407 
20408 NK_API int
20409 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
20410 {
20411  NK_ASSERT(ctx);
20412  if (!ctx) return 0;
20413  return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
20414 }
20415 
20416 NK_API int
20417 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
20418  struct nk_image img)
20419 {
20420  struct nk_window *win;
20421  struct nk_panel *layout;
20422  const struct nk_input *in;
20423 
20424  struct nk_rect bounds;
20425  enum nk_widget_layout_states state;
20426 
20427  NK_ASSERT(ctx);
20428  NK_ASSERT(ctx->current);
20429  NK_ASSERT(ctx->current->layout);
20430  if (!ctx || !ctx->current || !ctx->current->layout)
20431  return 0;
20432 
20433  win = ctx->current;
20434  layout = win->layout;
20435 
20436  state = nk_widget(&bounds, ctx);
20437  if (!state) return 0;
20438  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20439  return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
20440  img, ctx->button_behavior, style, in);
20441 }
20442 
20443 NK_API int
20444 nk_button_image(struct nk_context *ctx, struct nk_image img)
20445 {
20446  NK_ASSERT(ctx);
20447  if (!ctx) return 0;
20448  return nk_button_image_styled(ctx, &ctx->style.button, img);
20449 }
20450 
20451 NK_API int
20453  const struct nk_style_button *style, enum nk_symbol_type symbol,
20454  const char *text, int len, nk_flags align)
20455 {
20456  struct nk_window *win;
20457  struct nk_panel *layout;
20458  const struct nk_input *in;
20459 
20460  struct nk_rect bounds;
20461  enum nk_widget_layout_states state;
20462 
20463  NK_ASSERT(ctx);
20464  NK_ASSERT(ctx->current);
20465  NK_ASSERT(ctx->current->layout);
20466  if (!ctx || !ctx->current || !ctx->current->layout)
20467  return 0;
20468 
20469  win = ctx->current;
20470  layout = win->layout;
20471 
20472  state = nk_widget(&bounds, ctx);
20473  if (!state) return 0;
20474  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20475  return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20476  symbol, text, len, align, ctx->button_behavior,
20477  style, ctx->style.font, in);
20478 }
20479 
20480 NK_API int
20481 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
20482  const char* text, int len, nk_flags align)
20483 {
20484  NK_ASSERT(ctx);
20485  if (!ctx) return 0;
20486  return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
20487 }
20488 
20489 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
20490  const char *label, nk_flags align)
20491 {return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);}
20492 
20494  const struct nk_style_button *style, enum nk_symbol_type symbol,
20495  const char *title, nk_flags align)
20496 {return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);}
20497 
20498 NK_API int
20500  const struct nk_style_button *style, struct nk_image img, const char *text,
20501  int len, nk_flags align)
20502 {
20503  struct nk_window *win;
20504  struct nk_panel *layout;
20505  const struct nk_input *in;
20506 
20507  struct nk_rect bounds;
20508  enum nk_widget_layout_states state;
20509 
20510  NK_ASSERT(ctx);
20511  NK_ASSERT(ctx->current);
20512  NK_ASSERT(ctx->current->layout);
20513  if (!ctx || !ctx->current || !ctx->current->layout)
20514  return 0;
20515 
20516  win = ctx->current;
20517  layout = win->layout;
20518 
20519  state = nk_widget(&bounds, ctx);
20520  if (!state) return 0;
20521  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20522  return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
20523  bounds, img, text, len, align, ctx->button_behavior,
20524  style, ctx->style.font, in);
20525 }
20526 
20527 NK_API int
20528 nk_button_image_text(struct nk_context *ctx, struct nk_image img,
20529  const char *text, int len, nk_flags align)
20530 {return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);}
20531 
20532 
20533 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img,
20534  const char *label, nk_flags align)
20535 {return nk_button_image_text(ctx, img, label, nk_strlen(label), align);}
20536 
20538  const struct nk_style_button *style, struct nk_image img,
20539  const char *label, nk_flags text_alignment)
20540 {return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);}
20541 
20542 /*----------------------------------------------------------------
20543  *
20544  * SELECTABLE
20545  *
20546  * --------------------------------------------------------------*/
20547 NK_API int
20548 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
20549  nk_flags align, int *value)
20550 {
20551  struct nk_window *win;
20552  struct nk_panel *layout;
20553  const struct nk_input *in;
20554  const struct nk_style *style;
20555 
20556  enum nk_widget_layout_states state;
20557  struct nk_rect bounds;
20558 
20559  NK_ASSERT(ctx);
20560  NK_ASSERT(value);
20561  NK_ASSERT(ctx->current);
20562  NK_ASSERT(ctx->current->layout);
20563  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20564  return 0;
20565 
20566  win = ctx->current;
20567  layout = win->layout;
20568  style = &ctx->style;
20569 
20570  state = nk_widget(&bounds, ctx);
20571  if (!state) return 0;
20572  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20573  return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
20574  str, len, align, value, &style->selectable, in, style->font);
20575 }
20576 
20577 NK_API int
20578 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
20579  const char *str, int len, nk_flags align, int *value)
20580 {
20581  struct nk_window *win;
20582  struct nk_panel *layout;
20583  const struct nk_input *in;
20584  const struct nk_style *style;
20585 
20586  enum nk_widget_layout_states state;
20587  struct nk_rect bounds;
20588 
20589  NK_ASSERT(ctx);
20590  NK_ASSERT(value);
20591  NK_ASSERT(ctx->current);
20592  NK_ASSERT(ctx->current->layout);
20593  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20594  return 0;
20595 
20596  win = ctx->current;
20597  layout = win->layout;
20598  style = &ctx->style;
20599 
20600  state = nk_widget(&bounds, ctx);
20601  if (!state) return 0;
20602  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20603  return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
20604  str, len, align, value, &img, &style->selectable, in, style->font);
20605 }
20606 
20607 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len,
20608  nk_flags align, int value)
20609 {nk_selectable_text(ctx, str, len, align, &value);return value;}
20610 
20611 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value)
20612 {return nk_selectable_text(ctx, str, nk_strlen(str), align, value);}
20613 
20614 NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img,
20615  const char *str, nk_flags align, int *value)
20616 {return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);}
20617 
20618 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value)
20619 {nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;}
20620 
20621 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img,
20622  const char *str, nk_flags align, int value)
20623 {nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;}
20624 
20625 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img,
20626  const char *str, int len, nk_flags align, int value)
20627 {nk_selectable_image_text(ctx, img, str, len, align, &value);return value;}
20628 
20629 /*----------------------------------------------------------------
20630  *
20631  * CHECKBOX
20632  *
20633  * --------------------------------------------------------------*/
20634 NK_API int
20635 nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
20636 {
20637  struct nk_window *win;
20638  struct nk_panel *layout;
20639  const struct nk_input *in;
20640  const struct nk_style *style;
20641 
20642  struct nk_rect bounds;
20643  enum nk_widget_layout_states state;
20644 
20645  NK_ASSERT(ctx);
20646  NK_ASSERT(ctx->current);
20647  NK_ASSERT(ctx->current->layout);
20648  if (!ctx || !ctx->current || !ctx->current->layout)
20649  return active;
20650 
20651  win = ctx->current;
20652  style = &ctx->style;
20653  layout = win->layout;
20654 
20655  state = nk_widget(&bounds, ctx);
20656  if (!state) return active;
20657  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20658  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
20659  text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
20660  return active;
20661 }
20662 
20663 NK_API unsigned int
20664 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
20665  unsigned int flags, unsigned int value)
20666 {
20667  int old_active;
20668  NK_ASSERT(ctx);
20669  NK_ASSERT(text);
20670  if (!ctx || !text) return flags;
20671  old_active = (int)((flags & value) & value);
20672  if (nk_check_text(ctx, text, len, old_active))
20673  flags |= value;
20674  else flags &= ~value;
20675  return flags;
20676 }
20677 
20678 NK_API int
20679 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
20680 {
20681  int old_val;
20682  NK_ASSERT(ctx);
20683  NK_ASSERT(text);
20684  NK_ASSERT(active);
20685  if (!ctx || !text || !active) return 0;
20686  old_val = *active;
20687  *active = nk_check_text(ctx, text, len, *active);
20688  return old_val != *active;
20689 }
20690 
20691 NK_API int
20692 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
20693  unsigned int *flags, unsigned int value)
20694 {
20695  int active;
20696  NK_ASSERT(ctx);
20697  NK_ASSERT(text);
20698  NK_ASSERT(flags);
20699  if (!ctx || !text || !flags) return 0;
20700 
20701  active = (int)((*flags & value) & value);
20702  if (nk_checkbox_text(ctx, text, len, &active)) {
20703  if (active) *flags |= value;
20704  else *flags &= ~value;
20705  return 1;
20706  }
20707  return 0;
20708 }
20709 
20710 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
20711 {return nk_check_text(ctx, label, nk_strlen(label), active);}
20712 
20713 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
20714  unsigned int flags, unsigned int value)
20715 {return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);}
20716 
20717 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
20718 {return nk_checkbox_text(ctx, label, nk_strlen(label), active);}
20719 
20720 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
20721  unsigned int *flags, unsigned int value)
20722 {return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);}
20723 
20724 /*----------------------------------------------------------------
20725  *
20726  * OPTION
20727  *
20728  * --------------------------------------------------------------*/
20729 NK_API int
20730 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
20731 {
20732  struct nk_window *win;
20733  struct nk_panel *layout;
20734  const struct nk_input *in;
20735  const struct nk_style *style;
20736 
20737  struct nk_rect bounds;
20738  enum nk_widget_layout_states state;
20739 
20740  NK_ASSERT(ctx);
20741  NK_ASSERT(ctx->current);
20742  NK_ASSERT(ctx->current->layout);
20743  if (!ctx || !ctx->current || !ctx->current->layout)
20744  return is_active;
20745 
20746  win = ctx->current;
20747  style = &ctx->style;
20748  layout = win->layout;
20749 
20750  state = nk_widget(&bounds, ctx);
20751  if (!state) return state;
20752  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20753  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
20754  text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
20755  return is_active;
20756 }
20757 
20758 NK_API int
20759 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
20760 {
20761  int old_value;
20762  NK_ASSERT(ctx);
20763  NK_ASSERT(text);
20764  NK_ASSERT(active);
20765  if (!ctx || !text || !active) return 0;
20766  old_value = *active;
20767  *active = nk_option_text(ctx, text, len, old_value);
20768  return old_value != *active;
20769 }
20770 
20771 NK_API int
20772 nk_option_label(struct nk_context *ctx, const char *label, int active)
20773 {return nk_option_text(ctx, label, nk_strlen(label), active);}
20774 
20775 NK_API int
20776 nk_radio_label(struct nk_context *ctx, const char *label, int *active)
20777 {return nk_radio_text(ctx, label, nk_strlen(label), active);}
20778 
20779 /*----------------------------------------------------------------
20780  *
20781  * SLIDER
20782  *
20783  * --------------------------------------------------------------*/
20784 NK_API int
20785 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
20786  float value_step)
20787 {
20788  struct nk_window *win;
20789  struct nk_panel *layout;
20790  struct nk_input *in;
20791  const struct nk_style *style;
20792 
20793  int ret = 0;
20794  float old_value;
20795  struct nk_rect bounds;
20796  enum nk_widget_layout_states state;
20797 
20798  NK_ASSERT(ctx);
20799  NK_ASSERT(ctx->current);
20800  NK_ASSERT(ctx->current->layout);
20801  NK_ASSERT(value);
20802  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20803  return ret;
20804 
20805  win = ctx->current;
20806  style = &ctx->style;
20807  layout = win->layout;
20808 
20809  state = nk_widget(&bounds, ctx);
20810  if (!state) return ret;
20811  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20812 
20813  old_value = *value;
20814  *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
20815  old_value, max_value, value_step, &style->slider, in, style->font);
20816  return (old_value > *value || old_value < *value);
20817 }
20818 
20819 NK_API float
20820 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
20821 {
20822  nk_slider_float(ctx, min, &val, max, step); return val;
20823 }
20824 
20825 NK_API int
20826 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
20827 {
20828  float value = (float)val;
20829  nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
20830  return (int)value;
20831 }
20832 
20833 NK_API int
20834 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
20835 {
20836  int ret;
20837  float value = (float)*val;
20838  ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
20839  *val = (int)value;
20840  return ret;
20841 }
20842 
20843 /*----------------------------------------------------------------
20844  *
20845  * PROGRESSBAR
20846  *
20847  * --------------------------------------------------------------*/
20848 NK_API int
20849 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable)
20850 {
20851  struct nk_window *win;
20852  struct nk_panel *layout;
20853  const struct nk_style *style;
20854  const struct nk_input *in;
20855 
20856  struct nk_rect bounds;
20857  enum nk_widget_layout_states state;
20858  nk_size old_value;
20859 
20860  NK_ASSERT(ctx);
20861  NK_ASSERT(cur);
20862  NK_ASSERT(ctx->current);
20863  NK_ASSERT(ctx->current->layout);
20864  if (!ctx || !ctx->current || !ctx->current->layout || !cur)
20865  return 0;
20866 
20867  win = ctx->current;
20868  style = &ctx->style;
20869  layout = win->layout;
20870  state = nk_widget(&bounds, ctx);
20871  if (!state) return 0;
20872 
20873  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20874  old_value = *cur;
20875  *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
20876  *cur, max, is_modifyable, &style->progress, in);
20877  return (*cur != old_value);
20878 }
20879 
20880 NK_API nk_size nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable)
20881 {nk_progress(ctx, &cur, max, modifyable);return cur;}
20882 
20883 /*----------------------------------------------------------------
20884  *
20885  * EDIT
20886  *
20887  * --------------------------------------------------------------*/
20888 NK_API void
20889 nk_edit_focus(struct nk_context *ctx, nk_flags flags)
20890 {
20891  nk_hash hash;
20892  struct nk_window *win;
20893 
20894  NK_ASSERT(ctx);
20895  NK_ASSERT(ctx->current);
20896  if (!ctx || !ctx->current) return;
20897 
20898  win = ctx->current;
20899  hash = win->edit.seq;
20900  win->edit.active = nk_true;
20901  win->edit.name = hash;
20902  if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
20904 }
20905 
20906 NK_API void
20907 nk_edit_unfocus(struct nk_context *ctx)
20908 {
20909  struct nk_window *win;
20910  NK_ASSERT(ctx);
20911  NK_ASSERT(ctx->current);
20912  if (!ctx || !ctx->current) return;
20913 
20914  win = ctx->current;
20915  win->edit.active = nk_false;
20916  win->edit.name = 0;
20917 }
20918 
20919 NK_API nk_flags
20920 nk_edit_string(struct nk_context *ctx, nk_flags flags,
20921  char *memory, int *len, int max, nk_plugin_filter filter)
20922 {
20923  nk_hash hash;
20924  nk_flags state;
20925  struct nk_text_edit *edit;
20926  struct nk_window *win;
20927 
20928  NK_ASSERT(ctx);
20929  NK_ASSERT(memory);
20930  NK_ASSERT(len);
20931  if (!ctx || !memory || !len)
20932  return 0;
20933 
20934  filter = (!filter) ? nk_filter_default: filter;
20935  win = ctx->current;
20936  hash = win->edit.seq;
20937  edit = &ctx->text_edit;
20938  nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
20940 
20941  if (win->edit.active && hash == win->edit.name) {
20942  if (flags & NK_EDIT_NO_CURSOR)
20943  edit->cursor = nk_utf_len(memory, *len);
20944  else edit->cursor = win->edit.cursor;
20945  if (!(flags & NK_EDIT_SELECTABLE)) {
20946  edit->select_start = win->edit.cursor;
20947  edit->select_end = win->edit.cursor;
20948  } else {
20949  edit->select_start = win->edit.sel_start;
20950  edit->select_end = win->edit.sel_end;
20951  }
20952  edit->mode = win->edit.mode;
20953  edit->scrollbar.x = (float)win->edit.scrollbar.x;
20954  edit->scrollbar.y = (float)win->edit.scrollbar.y;
20955  edit->active = nk_true;
20956  } else edit->active = nk_false;
20957 
20958  max = NK_MAX(1, max);
20959  *len = NK_MIN(*len, max-1);
20960  nk_str_init_fixed(&edit->string, memory, (nk_size)max);
20961  edit->string.buffer.allocated = (nk_size)*len;
20962  edit->string.len = nk_utf_len(memory, *len);
20963  state = nk_edit_buffer(ctx, flags, edit, filter);
20964  *len = (int)edit->string.buffer.allocated;
20965 
20966  if (edit->active) {
20967  win->edit.cursor = edit->cursor;
20968  win->edit.sel_start = edit->select_start;
20969  win->edit.sel_end = edit->select_end;
20970  win->edit.mode = edit->mode;
20971  win->edit.scrollbar.x = (nk_ushort)edit->scrollbar.x;
20972  win->edit.scrollbar.y = (nk_ushort)edit->scrollbar.y;
20973  }
20974  return state;
20975 }
20976 
20977 NK_API nk_flags
20978 nk_edit_buffer(struct nk_context *ctx, nk_flags flags,
20979  struct nk_text_edit *edit, nk_plugin_filter filter)
20980 {
20981  struct nk_window *win;
20982  struct nk_style *style;
20983  struct nk_input *in;
20984 
20985  enum nk_widget_layout_states state;
20986  struct nk_rect bounds;
20987 
20988  nk_flags ret_flags = 0;
20989  unsigned char prev_state;
20990  nk_hash hash;
20991 
20992  /* make sure correct values */
20993  NK_ASSERT(ctx);
20994  NK_ASSERT(edit);
20995  NK_ASSERT(ctx->current);
20996  NK_ASSERT(ctx->current->layout);
20997  if (!ctx || !ctx->current || !ctx->current->layout)
20998  return 0;
20999 
21000  win = ctx->current;
21001  style = &ctx->style;
21002  state = nk_widget(&bounds, ctx);
21003  if (!state) return state;
21004  in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21005 
21006  /* check if edit is currently hot item */
21007  hash = win->edit.seq++;
21008  if (win->edit.active && hash == win->edit.name) {
21009  if (flags & NK_EDIT_NO_CURSOR)
21010  edit->cursor = edit->string.len;
21011  if (!(flags & NK_EDIT_SELECTABLE)) {
21012  edit->select_start = edit->cursor;
21013  edit->select_end = edit->cursor;
21014  }
21015  if (flags & NK_EDIT_CLIPBOARD)
21016  edit->clip = ctx->clip;
21017  }
21018 
21019  filter = (!filter) ? nk_filter_default: filter;
21020  prev_state = (unsigned char)edit->active;
21021  in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
21022  ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
21023  filter, edit, &style->edit, in, style->font);
21024 
21025  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
21027  if (edit->active && prev_state != edit->active) {
21028  /* current edit is now hot */
21029  win->edit.active = nk_true;
21030  win->edit.name = hash;
21031  } else if (prev_state && !edit->active) {
21032  /* current edit is now cold */
21033  win->edit.active = nk_false;
21034  }
21035  return ret_flags;
21036 }
21037 
21038 NK_API nk_flags
21039 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags,
21040  char *buffer, int max, nk_plugin_filter filter)
21041 {
21042  nk_flags result;
21043  int len = nk_strlen(buffer);
21044  result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
21045  buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
21046  return result;
21047 }
21048 
21049 /*----------------------------------------------------------------
21050  *
21051  * PROPERTY
21052  *
21053  * --------------------------------------------------------------*/
21054 NK_INTERN struct nk_property_variant
21055 nk_property_variant_int(int value, int min_value, int max_value, int step)
21056 {
21057  struct nk_property_variant result;
21058  result.kind = NK_PROPERTY_INT;
21059  result.value.i = value;
21060  result.min_value.i = min_value;
21061  result.max_value.i = max_value;
21062  result.step.i = step;
21063  return result;
21064 }
21065 
21066 NK_INTERN struct nk_property_variant
21067 nk_property_variant_float(float value, float min_value, float max_value, float step)
21068 {
21069  struct nk_property_variant result;
21070  result.kind = NK_PROPERTY_FLOAT;
21071  result.value.f = value;
21072  result.min_value.f = min_value;
21073  result.max_value.f = max_value;
21074  result.step.f = step;
21075  return result;
21076 }
21077 
21078 NK_INTERN struct nk_property_variant
21079 nk_property_variant_double(double value, double min_value, double max_value,
21080  double step)
21081 {
21082  struct nk_property_variant result;
21083  result.kind = NK_PROPERTY_DOUBLE;
21084  result.value.d = value;
21085  result.min_value.d = min_value;
21086  result.max_value.d = max_value;
21087  result.step.d = step;
21088  return result;
21089 }
21090 
21091 NK_INTERN void
21092 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
21093  float inc_per_pixel, const enum nk_property_filter filter)
21094 {
21095  struct nk_window *win;
21096  struct nk_panel *layout;
21097  struct nk_input *in;
21098  const struct nk_style *style;
21099 
21100  struct nk_rect bounds;
21101  enum nk_widget_layout_states s;
21102 
21103  int *state = 0;
21104  nk_hash hash = 0;
21105  char *buffer = 0;
21106  int *len = 0;
21107  int *cursor = 0;
21108  int *select_begin = 0;
21109  int *select_end = 0;
21110  int old_state;
21111 
21112  char dummy_buffer[NK_MAX_NUMBER_BUFFER];
21113  int dummy_state = NK_PROPERTY_DEFAULT;
21114  int dummy_length = 0;
21115  int dummy_cursor = 0;
21116  int dummy_select_begin = 0;
21117  int dummy_select_end = 0;
21118 
21119  NK_ASSERT(ctx);
21120  NK_ASSERT(ctx->current);
21121  NK_ASSERT(ctx->current->layout);
21122  if (!ctx || !ctx->current || !ctx->current->layout)
21123  return;
21124 
21125  win = ctx->current;
21126  layout = win->layout;
21127  style = &ctx->style;
21128  s = nk_widget(&bounds, ctx);
21129  if (!s) return;
21130  in = (s == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21131 
21132  /* calculate hash from name */
21133  if (name[0] == '#') {
21134  hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
21135  name++; /* special number hash */
21136  } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
21137 
21138  /* check if property is currently hot item */
21139  if (win->property.active && hash == win->property.name) {
21140  buffer = win->property.buffer;
21141  len = &win->property.length;
21142  cursor = &win->property.cursor;
21143  state = &win->property.state;
21144  select_begin = &win->property.select_start;
21145  select_end = &win->property.select_end;
21146  } else {
21147  buffer = dummy_buffer;
21148  len = &dummy_length;
21149  cursor = &dummy_cursor;
21150  state = &dummy_state;
21151  select_begin = &dummy_select_begin;
21152  select_end = &dummy_select_end;
21153  }
21154 
21155  /* execute property widget */
21156  old_state = *state;
21157  ctx->text_edit.clip = ctx->clip;
21158  nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
21159  variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
21160  select_end, &style->property, filter, in, style->font, &ctx->text_edit,
21161  ctx->button_behavior);
21162 
21163  if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
21164  /* current property is now hot */
21165  win->property.active = 1;
21166  NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
21167  win->property.length = *len;
21168  win->property.cursor = *cursor;
21169  win->property.state = *state;
21170  win->property.name = hash;
21171  win->property.select_start = *select_begin;
21172  win->property.select_end = *select_end;
21173  if (*state == NK_PROPERTY_DRAG) {
21174  ctx->input.mouse.grab = nk_true;
21175  ctx->input.mouse.grabbed = nk_true;
21176  }
21177  }
21178 
21179  /* check if previously active property is now inactive */
21180  if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
21181  if (old_state == NK_PROPERTY_DRAG) {
21182  ctx->input.mouse.grab = nk_false;
21183  ctx->input.mouse.grabbed = nk_false;
21184  ctx->input.mouse.ungrab = nk_true;
21185  }
21186  win->property.active = 0;
21187  }
21188 }
21189 
21190 NK_API void
21191 nk_property_int(struct nk_context *ctx, const char *name,
21192  int min, int *val, int max, int step, float inc_per_pixel)
21193 {
21194  struct nk_property_variant variant;
21195  NK_ASSERT(ctx);
21196  NK_ASSERT(name);
21197  NK_ASSERT(val);
21198 
21199  if (!ctx || !ctx->current || !name || !val) return;
21200  variant = nk_property_variant_int(*val, min, max, step);
21201  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
21202  *val = variant.value.i;
21203 }
21204 
21205 NK_API void
21206 nk_property_float(struct nk_context *ctx, const char *name,
21207  float min, float *val, float max, float step, float inc_per_pixel)
21208 {
21209  struct nk_property_variant variant;
21210  NK_ASSERT(ctx);
21211  NK_ASSERT(name);
21212  NK_ASSERT(val);
21213 
21214  if (!ctx || !ctx->current || !name || !val) return;
21215  variant = nk_property_variant_float(*val, min, max, step);
21216  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21217  *val = variant.value.f;
21218 }
21219 
21220 NK_API void
21221 nk_property_double(struct nk_context *ctx, const char *name,
21222  double min, double *val, double max, double step, float inc_per_pixel)
21223 {
21224  struct nk_property_variant variant;
21225  NK_ASSERT(ctx);
21226  NK_ASSERT(name);
21227  NK_ASSERT(val);
21228 
21229  if (!ctx || !ctx->current || !name || !val) return;
21230  variant = nk_property_variant_double(*val, min, max, step);
21231  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21232  *val = variant.value.d;
21233 }
21234 
21235 NK_API int
21236 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
21237  int max, int step, float inc_per_pixel)
21238 {
21239  struct nk_property_variant variant;
21240  NK_ASSERT(ctx);
21241  NK_ASSERT(name);
21242 
21243  if (!ctx || !ctx->current || !name) return val;
21244  variant = nk_property_variant_int(val, min, max, step);
21245  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
21246  val = variant.value.i;
21247  return val;
21248 }
21249 
21250 NK_API float
21251 nk_propertyf(struct nk_context *ctx, const char *name, float min,
21252  float val, float max, float step, float inc_per_pixel)
21253 {
21254  struct nk_property_variant variant;
21255  NK_ASSERT(ctx);
21256  NK_ASSERT(name);
21257 
21258  if (!ctx || !ctx->current || !name) return val;
21259  variant = nk_property_variant_float(val, min, max, step);
21260  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21261  val = variant.value.f;
21262  return val;
21263 }
21264 
21265 NK_API double
21266 nk_propertyd(struct nk_context *ctx, const char *name, double min,
21267  double val, double max, double step, float inc_per_pixel)
21268 {
21269  struct nk_property_variant variant;
21270  NK_ASSERT(ctx);
21271  NK_ASSERT(name);
21272 
21273  if (!ctx || !ctx->current || !name) return val;
21274  variant = nk_property_variant_double(val, min, max, step);
21275  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21276  val = variant.value.d;
21277  return val;
21278 }
21279 
21280 /*----------------------------------------------------------------
21281  *
21282  * COLOR PICKER
21283  *
21284  * --------------------------------------------------------------*/
21285 NK_API int
21286 nk_color_pick(struct nk_context * ctx, struct nk_color *color,
21287  enum nk_color_format fmt)
21288 {
21289  struct nk_window *win;
21290  struct nk_panel *layout;
21291  const struct nk_style *config;
21292  const struct nk_input *in;
21293 
21294  enum nk_widget_layout_states state;
21295  struct nk_rect bounds;
21296 
21297  NK_ASSERT(ctx);
21298  NK_ASSERT(color);
21299  NK_ASSERT(ctx->current);
21300  NK_ASSERT(ctx->current->layout);
21301  if (!ctx || !ctx->current || !ctx->current->layout || !color)
21302  return 0;
21303 
21304  win = ctx->current;
21305  config = &ctx->style;
21306  layout = win->layout;
21307  state = nk_widget(&bounds, ctx);
21308  if (!state) return 0;
21309  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21310  return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
21311  nk_vec2(0,0), in, config->font);
21312 }
21313 
21314 NK_API struct nk_color
21315 nk_color_picker(struct nk_context *ctx, struct nk_color color,
21316  enum nk_color_format fmt)
21317 {
21318  nk_color_pick(ctx, &color, fmt);
21319  return color;
21320 }
21321 
21322 /* -------------------------------------------------------------
21323  *
21324  * CHART
21325  *
21326  * --------------------------------------------------------------*/
21327 NK_API int
21328 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
21329  struct nk_color color, struct nk_color highlight,
21330  int count, float min_value, float max_value)
21331 {
21332  struct nk_window *win;
21333  struct nk_chart *chart;
21334  const struct nk_style *config;
21335  const struct nk_style_chart *style;
21336 
21337  const struct nk_style_item *background;
21338  struct nk_rect bounds = {0, 0, 0, 0};
21339 
21340  NK_ASSERT(ctx);
21341  NK_ASSERT(ctx->current);
21342  NK_ASSERT(ctx->current->layout);
21343 
21344  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
21345  if (!nk_widget(&bounds, ctx)) {
21346  chart = &ctx->current->layout->chart;
21347  nk_zero(chart, sizeof(*chart));
21348  return 0;
21349  }
21350 
21351  win = ctx->current;
21352  config = &ctx->style;
21353  chart = &win->layout->chart;
21354  style = &config->chart;
21355 
21356  /* setup basic generic chart */
21357  nk_zero(chart, sizeof(*chart));
21358  chart->x = bounds.x + style->padding.x;
21359  chart->y = bounds.y + style->padding.y;
21360  chart->w = bounds.w - 2 * style->padding.x;
21361  chart->h = bounds.h - 2 * style->padding.y;
21362  chart->w = NK_MAX(chart->w, 2 * style->padding.x);
21363  chart->h = NK_MAX(chart->h, 2 * style->padding.y);
21364 
21365  /* add first slot into chart */
21366  {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
21367  slot->type = type;
21368  slot->count = count;
21369  slot->color = color;
21370  slot->highlight = highlight;
21371  slot->min = NK_MIN(min_value, max_value);
21372  slot->max = NK_MAX(min_value, max_value);
21373  slot->range = slot->max - slot->min;}
21374 
21375  /* draw chart background */
21376  background = &style->background;
21377  if (background->type == NK_STYLE_ITEM_IMAGE) {
21378  nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
21379  } else {
21380  nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
21381  nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
21382  style->rounding, style->background.data.color);
21383  }
21384  return 1;
21385 }
21386 
21387 NK_API int
21388 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
21389  int count, float min_value, float max_value)
21390 {return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
21391 
21392 NK_API void
21393 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type,
21394  struct nk_color color, struct nk_color highlight,
21395  int count, float min_value, float max_value)
21396 {
21397  NK_ASSERT(ctx);
21398  NK_ASSERT(ctx->current);
21399  NK_ASSERT(ctx->current->layout);
21400  NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
21401  if (!ctx || !ctx->current || !ctx->current->layout) return;
21402  if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
21403 
21404  /* add another slot into the graph */
21405  {struct nk_chart *chart = &ctx->current->layout->chart;
21406  struct nk_chart_slot *slot = &chart->slots[chart->slot++];
21407  slot->type = type;
21408  slot->count = count;
21409  slot->color = color;
21410  slot->highlight = highlight;
21411  slot->min = NK_MIN(min_value, max_value);
21412  slot->max = NK_MAX(min_value, max_value);
21413  slot->range = slot->max - slot->min;}
21414 }
21415 
21416 NK_API void
21417 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
21418  int count, float min_value, float max_value)
21419 {nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
21420 
21421 NK_INTERN nk_flags
21422 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
21423  struct nk_chart *g, float value, int slot)
21424 {
21425  struct nk_panel *layout = win->layout;
21426  const struct nk_input *i = &ctx->input;
21427  struct nk_command_buffer *out = &win->buffer;
21428 
21429  nk_flags ret = 0;
21430  struct nk_vec2 cur;
21431  struct nk_rect bounds;
21432  struct nk_color color;
21433  float step;
21434  float range;
21435  float ratio;
21436 
21437  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21438  step = g->w / (float)g->slots[slot].count;
21439  range = g->slots[slot].max - g->slots[slot].min;
21440  ratio = (value - g->slots[slot].min) / range;
21441 
21442  if (g->slots[slot].index == 0) {
21443  /* first data point does not have a connection */
21444  g->slots[slot].last.x = g->x;
21445  g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
21446 
21447  bounds.x = g->slots[slot].last.x - 2;
21448  bounds.y = g->slots[slot].last.y - 2;
21449  bounds.w = bounds.h = 4;
21450 
21451  color = g->slots[slot].color;
21452  if (!(layout->flags & NK_WINDOW_ROM) &&
21453  NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
21454  ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
21455  ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
21457  color = g->slots[slot].highlight;
21458  }
21459  nk_fill_rect(out, bounds, 0, color);
21460  g->slots[slot].index += 1;
21461  return ret;
21462  }
21463 
21464  /* draw a line between the last data point and the new one */
21465  color = g->slots[slot].color;
21466  cur.x = g->x + (float)(step * (float)g->slots[slot].index);
21467  cur.y = (g->y + g->h) - (ratio * (float)g->h);
21468  nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
21469 
21470  bounds.x = cur.x - 3;
21471  bounds.y = cur.y - 3;
21472  bounds.w = bounds.h = 6;
21473 
21474  /* user selection of current data point */
21475  if (!(layout->flags & NK_WINDOW_ROM)) {
21476  if (nk_input_is_mouse_hovering_rect(i, bounds)) {
21477  ret = NK_CHART_HOVERING;
21478  ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
21480  color = g->slots[slot].highlight;
21481  }
21482  }
21483  nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
21484 
21485  /* save current data point position */
21486  g->slots[slot].last.x = cur.x;
21487  g->slots[slot].last.y = cur.y;
21488  g->slots[slot].index += 1;
21489  return ret;
21490 }
21491 
21492 NK_INTERN nk_flags
21493 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
21494  struct nk_chart *chart, float value, int slot)
21495 {
21496  struct nk_command_buffer *out = &win->buffer;
21497  const struct nk_input *in = &ctx->input;
21498  struct nk_panel *layout = win->layout;
21499 
21500  float ratio;
21501  nk_flags ret = 0;
21502  struct nk_color color;
21503  struct nk_rect item = {0,0,0,0};
21504 
21505  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21506  if (chart->slots[slot].index >= chart->slots[slot].count)
21507  return nk_false;
21508  if (chart->slots[slot].count) {
21509  float padding = (float)(chart->slots[slot].count-1);
21510  item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
21511  }
21512 
21513  /* calculate bounds of current bar chart entry */
21514  color = chart->slots[slot].color;;
21515  item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
21516  if (value >= 0) {
21517  ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
21518  item.y = (chart->y + chart->h) - chart->h * ratio;
21519  } else {
21520  ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
21521  item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
21522  }
21523  item.x = chart->x + ((float)chart->slots[slot].index * item.w);
21524  item.x = item.x + ((float)chart->slots[slot].index);
21525 
21526  /* user chart bar selection */
21527  if (!(layout->flags & NK_WINDOW_ROM) &&
21528  NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
21529  ret = NK_CHART_HOVERING;
21530  ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
21532  color = chart->slots[slot].highlight;
21533  }
21534  nk_fill_rect(out, item, 0, color);
21535  chart->slots[slot].index += 1;
21536  return ret;
21537 }
21538 
21539 NK_API nk_flags
21540 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
21541 {
21542  nk_flags flags;
21543  struct nk_window *win;
21544 
21545  NK_ASSERT(ctx);
21546  NK_ASSERT(ctx->current);
21547  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21548  NK_ASSERT(slot < ctx->current->layout->chart.slot);
21549  if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
21550  if (slot >= ctx->current->layout->chart.slot) return nk_false;
21551 
21552  win = ctx->current;
21553  if (win->layout->chart.slot < slot) return nk_false;
21554  switch (win->layout->chart.slots[slot].type) {
21555  case NK_CHART_LINES:
21556  flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
21557  case NK_CHART_COLUMN:
21558  flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
21559  default:
21560  case NK_CHART_MAX:
21561  flags = 0;
21562  }
21563  return flags;
21564 }
21565 
21566 NK_API nk_flags
21567 nk_chart_push(struct nk_context *ctx, float value)
21568 {return nk_chart_push_slot(ctx, value, 0);}
21569 
21570 NK_API void
21571 nk_chart_end(struct nk_context *ctx)
21572 {
21573  struct nk_window *win;
21574  struct nk_chart *chart;
21575 
21576  NK_ASSERT(ctx);
21577  NK_ASSERT(ctx->current);
21578  if (!ctx || !ctx->current)
21579  return;
21580 
21581  win = ctx->current;
21582  chart = &win->layout->chart;
21583  NK_MEMSET(chart, 0, sizeof(*chart));
21584  return;
21585 }
21586 
21587 NK_API void
21588 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
21589  int count, int offset)
21590 {
21591  int i = 0;
21592  float min_value;
21593  float max_value;
21594 
21595  NK_ASSERT(ctx);
21596  NK_ASSERT(values);
21597  if (!ctx || !values || !count) return;
21598 
21599  min_value = values[offset];
21600  max_value = values[offset];
21601  for (i = 0; i < count; ++i) {
21602  min_value = NK_MIN(values[i + offset], min_value);
21603  max_value = NK_MAX(values[i + offset], max_value);
21604  }
21605  nk_chart_begin(ctx, type, count, min_value, max_value);
21606  for (i = 0; i < count; ++i)
21607  nk_chart_push(ctx, values[i + offset]);
21608  nk_chart_end(ctx);
21609 }
21610 
21611 NK_API void
21612 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
21613  float(*value_getter)(void* user, int index), int count, int offset)
21614 {
21615  int i = 0;
21616  float min_value;
21617  float max_value;
21618 
21619  NK_ASSERT(ctx);
21620  NK_ASSERT(value_getter);
21621  if (!ctx || !value_getter || !count) return;
21622 
21623  max_value = min_value = value_getter(userdata, offset);
21624  for (i = 0; i < count; ++i) {
21625  float value = value_getter(userdata, i + offset);
21626  min_value = NK_MIN(value, min_value);
21627  max_value = NK_MAX(value, max_value);
21628  }
21629  nk_chart_begin(ctx, type, count, min_value, max_value);
21630  for (i = 0; i < count; ++i)
21631  nk_chart_push(ctx, value_getter(userdata, i + offset));
21632  nk_chart_end(ctx);
21633 }
21634 
21635 /* -------------------------------------------------------------
21636  *
21637  * GROUP
21638  *
21639  * --------------------------------------------------------------*/
21640 NK_API int
21642  nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
21643 {
21644  struct nk_rect bounds;
21645  struct nk_window panel;
21646  struct nk_window *win;
21647 
21648  win = ctx->current;
21649  nk_panel_alloc_space(&bounds, ctx);
21650  {const struct nk_rect *c = &win->layout->clip;
21651  if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
21652  !(flags & NK_WINDOW_MOVABLE)) {
21653  return 0;
21654  }}
21655  if (win->flags & NK_WINDOW_ROM)
21656  flags |= NK_WINDOW_ROM;
21657 
21658  /* initialize a fake window to create the panel from */
21659  nk_zero(&panel, sizeof(panel));
21660  panel.bounds = bounds;
21661  panel.flags = flags;
21662  panel.scrollbar.x = *x_offset;
21663  panel.scrollbar.y = *y_offset;
21664  panel.buffer = win->buffer;
21665  panel.layout = (struct nk_panel*)nk_create_panel(ctx);
21666  ctx->current = &panel;
21667  nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
21668 
21669  win->buffer = panel.buffer;
21670  win->buffer.clip = panel.layout->clip;
21671  panel.layout->offset_x = x_offset;
21672  panel.layout->offset_y = y_offset;
21673  panel.layout->parent = win->layout;
21674  win->layout = panel.layout;
21675 
21676  ctx->current = win;
21677  if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
21678  (panel.layout->flags & NK_WINDOW_MINIMIZED))
21679  {
21680  nk_flags f = panel.layout->flags;
21681  nk_group_scrolled_end(ctx);
21682  if (f & NK_WINDOW_CLOSED)
21683  return NK_WINDOW_CLOSED;
21684  if (f & NK_WINDOW_MINIMIZED)
21685  return NK_WINDOW_MINIMIZED;
21686  }
21687  return 1;
21688 }
21689 
21690 NK_API void
21691 nk_group_scrolled_end(struct nk_context *ctx)
21692 {
21693  struct nk_window *win;
21694  struct nk_panel *parent;
21695  struct nk_panel *g;
21696 
21697  struct nk_rect clip;
21698  struct nk_window pan;
21699  struct nk_vec2 panel_padding;
21700 
21701  NK_ASSERT(ctx);
21702  NK_ASSERT(ctx->current);
21703  if (!ctx || !ctx->current)
21704  return;
21705 
21706  /* make sure nk_group_begin was called correctly */
21707  NK_ASSERT(ctx->current);
21708  win = ctx->current;
21709  NK_ASSERT(win->layout);
21710  g = win->layout;
21711  NK_ASSERT(g->parent);
21712  parent = g->parent;
21713 
21714  /* dummy window */
21715  nk_zero_struct(pan);
21716  panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
21717  pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
21718  pan.bounds.x = g->bounds.x - panel_padding.x;
21719  pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
21720  pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
21721  if (g->flags & NK_WINDOW_BORDER) {
21722  pan.bounds.x -= g->border;
21723  pan.bounds.y -= g->border;
21724  pan.bounds.w += 2*g->border;
21725  pan.bounds.h += 2*g->border;
21726  }
21727  if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
21728  pan.bounds.w += ctx->style.window.scrollbar_size.x;
21729  pan.bounds.h += ctx->style.window.scrollbar_size.y;
21730  }
21731  pan.scrollbar.x = *g->offset_x;
21732  pan.scrollbar.y = *g->offset_y;
21733  pan.flags = g->flags;
21734  pan.buffer = win->buffer;
21735  pan.layout = g;
21736  pan.parent = win;
21737  ctx->current = &pan;
21738 
21739  /* make sure group has correct clipping rectangle */
21740  nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
21741  pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
21742  nk_push_scissor(&pan.buffer, clip);
21743  nk_end(ctx);
21744 
21745  win->buffer = pan.buffer;
21746  nk_push_scissor(&win->buffer, parent->clip);
21747  ctx->current = win;
21748  win->layout = parent;
21749  g->bounds = pan.bounds;
21750  return;
21751 }
21752 
21753 NK_API int
21755  struct nk_scroll *scroll, const char *title, nk_flags flags)
21756 {return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);}
21757 
21758 NK_API int
21759 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
21760 {
21761  int title_len;
21762  nk_hash title_hash;
21763  struct nk_window *win;
21764  nk_uint *x_offset;
21765  nk_uint *y_offset;
21766 
21767  NK_ASSERT(ctx);
21768  NK_ASSERT(title);
21769  NK_ASSERT(ctx->current);
21770  NK_ASSERT(ctx->current->layout);
21771  if (!ctx || !ctx->current || !ctx->current->layout || !title)
21772  return 0;
21773 
21774  /* find persistent group scrollbar value */
21775  win = ctx->current;
21776  title_len = (int)nk_strlen(title);
21777  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
21778  x_offset = nk_find_value(win, title_hash);
21779  if (!x_offset) {
21780  x_offset = nk_add_value(ctx, win, title_hash, 0);
21781  y_offset = nk_add_value(ctx, win, title_hash+1, 0);
21782 
21783  NK_ASSERT(x_offset);
21784  NK_ASSERT(y_offset);
21785  if (!x_offset || !y_offset) return 0;
21786  *x_offset = *y_offset = 0;
21787  } else y_offset = nk_find_value(win, title_hash+1);
21788  return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
21789 }
21790 
21791 NK_API void
21792 nk_group_end(struct nk_context *ctx)
21793 {nk_group_scrolled_end(ctx);}
21794 
21795 NK_API int
21796 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
21797  const char *title, nk_flags flags, int row_height, int row_count)
21798 {
21799  int title_len;
21800  nk_hash title_hash;
21801  nk_uint *x_offset;
21802  nk_uint *y_offset;
21803 
21804  int result;
21805  struct nk_window *win;
21806  struct nk_panel *layout;
21807  const struct nk_style *style;
21808  struct nk_vec2 item_spacing;
21809 
21810  NK_ASSERT(ctx);
21811  NK_ASSERT(view);
21812  NK_ASSERT(title);
21813  if (!ctx || !view || !title) return 0;
21814 
21815  win = ctx->current;
21816  style = &ctx->style;
21817  item_spacing = style->window.spacing;
21818  row_height += NK_MAX(0, (int)item_spacing.y);
21819 
21820  /* find persistent list view scrollbar offset */
21821  title_len = (int)nk_strlen(title);
21822  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
21823  x_offset = nk_find_value(win, title_hash);
21824  if (!x_offset) {
21825  x_offset = nk_add_value(ctx, win, title_hash, 0);
21826  y_offset = nk_add_value(ctx, win, title_hash+1, 0);
21827 
21828  NK_ASSERT(x_offset);
21829  NK_ASSERT(y_offset);
21830  if (!x_offset || !y_offset) return 0;
21831  *x_offset = *y_offset = 0;
21832  } else y_offset = nk_find_value(win, title_hash+1);
21833  view->scroll_value = *y_offset;
21834  view->scroll_pointer = y_offset;
21835 
21836  *y_offset = 0;
21837  result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
21838  win = ctx->current;
21839  layout = win->layout;
21840 
21841  view->total_height = row_height * NK_MAX(row_count,1);
21842  view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
21843  view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height), 0);
21844  view->end = view->begin + view->count;
21845  view->ctx = ctx;
21846  return result;
21847 }
21848 
21849 NK_API void
21850 nk_list_view_end(struct nk_list_view *view)
21851 {
21852  struct nk_context *ctx;
21853  struct nk_window *win;
21854  struct nk_panel *layout;
21855 
21856  NK_ASSERT(view);
21857  NK_ASSERT(view->ctx);
21858  NK_ASSERT(view->scroll_pointer);
21859  if (!view || !view->ctx) return;
21860 
21861  ctx = view->ctx;
21862  win = ctx->current;
21863  layout = win->layout;
21864  layout->at_y = layout->bounds.y + (float)view->total_height;
21865  *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
21866  nk_group_end(view->ctx);
21867 }
21868 
21869 /* --------------------------------------------------------------
21870  *
21871  * POPUP
21872  *
21873  * --------------------------------------------------------------*/
21874 NK_API int
21875 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
21876  const char *title, nk_flags flags, struct nk_rect rect)
21877 {
21878  struct nk_window *popup;
21879  struct nk_window *win;
21880  struct nk_panel *panel;
21881 
21882  int title_len;
21883  nk_hash title_hash;
21884  nk_size allocated;
21885 
21886  NK_ASSERT(ctx);
21887  NK_ASSERT(title);
21888  NK_ASSERT(ctx->current);
21889  NK_ASSERT(ctx->current->layout);
21890  if (!ctx || !ctx->current || !ctx->current->layout)
21891  return 0;
21892 
21893  win = ctx->current;
21894  panel = win->layout;
21895  NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
21896  (void)panel;
21897  title_len = (int)nk_strlen(title);
21898  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
21899 
21900  popup = win->popup.win;
21901  if (!popup) {
21902  popup = (struct nk_window*)nk_create_window(ctx);
21903  popup->parent = win;
21904  win->popup.win = popup;
21905  win->popup.active = 0;
21906  win->popup.type = NK_PANEL_POPUP;
21907  }
21908 
21909  /* make sure we have to correct popup */
21910  if (win->popup.name != title_hash) {
21911  if (!win->popup.active) {
21912  nk_zero(popup, sizeof(*popup));
21913  win->popup.name = title_hash;
21914  win->popup.active = 1;
21915  win->popup.type = NK_PANEL_POPUP;
21916  } else return 0;
21917  }
21918 
21919  /* popup position is local to window */
21920  ctx->current = popup;
21921  rect.x += win->layout->clip.x;
21922  rect.y += win->layout->clip.y;
21923 
21924  /* setup popup data */
21925  popup->parent = win;
21926  popup->bounds = rect;
21927  popup->seq = ctx->seq;
21928  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
21929  popup->flags = flags;
21930  popup->flags |= NK_WINDOW_BORDER;
21931  if (type == NK_POPUP_DYNAMIC)
21932  popup->flags |= NK_WINDOW_DYNAMIC;
21933 
21934  popup->buffer = win->buffer;
21935  nk_start_popup(ctx, win);
21936  allocated = ctx->memory.allocated;
21937  nk_push_scissor(&popup->buffer, nk_null_rect);
21938 
21939  if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
21940  /* popup is running therefore invalidate parent panels */
21941  struct nk_panel *root;
21942  root = win->layout;
21943  while (root) {
21944  root->flags |= NK_WINDOW_ROM;
21945  root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
21946  root = root->parent;
21947  }
21948  win->popup.active = 1;
21949  popup->layout->offset_x = &popup->scrollbar.x;
21950  popup->layout->offset_y = &popup->scrollbar.y;
21951  popup->layout->parent = win->layout;
21952  return 1;
21953  } else {
21954  /* popup was closed/is invalid so cleanup */
21955  struct nk_panel *root;
21956  root = win->layout;
21957  while (root) {
21958  root->flags |= NK_WINDOW_REMOVE_ROM;
21959  root = root->parent;
21960  }
21961  win->popup.buf.active = 0;
21962  win->popup.active = 0;
21963  ctx->memory.allocated = allocated;
21964  ctx->current = win;
21965  nk_free_panel(ctx, popup->layout);
21966  popup->layout = 0;
21967  return 0;
21968  }
21969 }
21970 
21971 NK_INTERN int
21972 nk_nonblock_begin(struct nk_context *ctx,
21973  nk_flags flags, struct nk_rect body, struct nk_rect header,
21974  enum nk_panel_type panel_type)
21975 {
21976  struct nk_window *popup;
21977  struct nk_window *win;
21978  struct nk_panel *panel;
21979  int is_active = nk_true;
21980 
21981  NK_ASSERT(ctx);
21982  NK_ASSERT(ctx->current);
21983  NK_ASSERT(ctx->current->layout);
21984  if (!ctx || !ctx->current || !ctx->current->layout)
21985  return 0;
21986 
21987  /* popups cannot have popups */
21988  win = ctx->current;
21989  panel = win->layout;
21990  NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
21991  (void)panel;
21992  popup = win->popup.win;
21993  if (!popup) {
21994  /* create window for nonblocking popup */
21995  popup = (struct nk_window*)nk_create_window(ctx);
21996  popup->parent = win;
21997  win->popup.win = popup;
21998  win->popup.type = panel_type;
21999  nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
22000  } else {
22001  /* close the popup if user pressed outside or in the header */
22002  int pressed, in_body, in_header;
22004  in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
22005  in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
22006  if (pressed && (!in_body || in_header))
22007  is_active = nk_false;
22008  }
22009  win->popup.header = header;
22010 
22011  if (!is_active) {
22012  /* remove read only mode from all parent panels */
22013  struct nk_panel *root = win->layout;
22014  while (root) {
22015  root->flags |= NK_WINDOW_REMOVE_ROM;
22016  root = root->parent;
22017  }
22018  return is_active;
22019  }
22020 
22021  popup->bounds = body;
22022  popup->parent = win;
22023  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
22024  popup->flags = flags;
22025  popup->flags |= NK_WINDOW_BORDER;
22026  popup->flags |= NK_WINDOW_DYNAMIC;
22027  popup->seq = ctx->seq;
22028  win->popup.active = 1;
22029  NK_ASSERT(popup->layout);
22030 
22031  nk_start_popup(ctx, win);
22032  popup->buffer = win->buffer;
22033  nk_push_scissor(&popup->buffer, nk_null_rect);
22034  ctx->current = popup;
22035 
22036  nk_panel_begin(ctx, 0, panel_type);
22037  win->buffer = popup->buffer;
22038  popup->layout->parent = win->layout;
22039  popup->layout->offset_x = &popup->scrollbar.x;
22040  popup->layout->offset_y = &popup->scrollbar.y;
22041 
22042  /* set read only mode to all parent panels */
22043  {struct nk_panel *root;
22044  root = win->layout;
22045  while (root) {
22046  root->flags |= NK_WINDOW_ROM;
22047  root = root->parent;
22048  }}
22049  return is_active;
22050 }
22051 
22052 NK_API void
22053 nk_popup_close(struct nk_context *ctx)
22054 {
22055  struct nk_window *popup;
22056  NK_ASSERT(ctx);
22057  if (!ctx || !ctx->current) return;
22058 
22059  popup = ctx->current;
22060  NK_ASSERT(popup->parent);
22061  NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
22062  popup->flags |= NK_WINDOW_HIDDEN;
22063 }
22064 
22065 NK_API void
22066 nk_popup_end(struct nk_context *ctx)
22067 {
22068  struct nk_window *win;
22069  struct nk_window *popup;
22070 
22071  NK_ASSERT(ctx);
22072  NK_ASSERT(ctx->current);
22073  NK_ASSERT(ctx->current->layout);
22074  if (!ctx || !ctx->current || !ctx->current->layout)
22075  return;
22076 
22077  popup = ctx->current;
22078  if (!popup->parent) return;
22079  win = popup->parent;
22080  if (popup->flags & NK_WINDOW_HIDDEN) {
22081  struct nk_panel *root;
22082  root = win->layout;
22083  while (root) {
22084  root->flags |= NK_WINDOW_REMOVE_ROM;
22085  root = root->parent;
22086  }
22087  win->popup.active = 0;
22088  }
22089  nk_push_scissor(&popup->buffer, nk_null_rect);
22090  nk_end(ctx);
22091 
22092  win->buffer = popup->buffer;
22093  nk_finish_popup(ctx, win);
22094  ctx->current = win;
22095  nk_push_scissor(&win->buffer, win->layout->clip);
22096 }
22097 /* -------------------------------------------------------------
22098  *
22099  * TOOLTIP
22100  *
22101  * -------------------------------------------------------------- */
22102 NK_API int
22103 nk_tooltip_begin(struct nk_context *ctx, float width)
22104 {
22105  struct nk_window *win;
22106  const struct nk_input *in;
22107  struct nk_rect bounds;
22108  int ret;
22109 
22110  NK_ASSERT(ctx);
22111  NK_ASSERT(ctx->current);
22112  NK_ASSERT(ctx->current->layout);
22113  if (!ctx || !ctx->current || !ctx->current->layout)
22114  return 0;
22115 
22116  /* make sure that no nonblocking popup is currently active */
22117  win = ctx->current;
22118  in = &ctx->input;
22119  if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
22120  return 0;
22121 
22122  bounds.w = width;
22123  bounds.h = nk_null_rect.h;
22124  bounds.x = (in->mouse.pos.x + 1) - win->layout->clip.x;
22125  bounds.y = (in->mouse.pos.y + 1) - win->layout->clip.y;
22126 
22127  ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC,
22128  "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
22129  if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
22130  win->popup.type = NK_PANEL_TOOLTIP;
22132  return ret;
22133 }
22134 
22135 NK_API void
22136 nk_tooltip_end(struct nk_context *ctx)
22137 {
22138  NK_ASSERT(ctx);
22139  NK_ASSERT(ctx->current);
22140  if (!ctx || !ctx->current) return;
22141  ctx->current->seq--;
22142  nk_popup_close(ctx);
22143  nk_popup_end(ctx);
22144 }
22145 
22146 NK_API void
22147 nk_tooltip(struct nk_context *ctx, const char *text)
22148 {
22149  const struct nk_style *style;
22150  struct nk_vec2 padding;
22151 
22152  int text_len;
22153  float text_width;
22154  float text_height;
22155 
22156  NK_ASSERT(ctx);
22157  NK_ASSERT(ctx->current);
22158  NK_ASSERT(ctx->current->layout);
22159  NK_ASSERT(text);
22160  if (!ctx || !ctx->current || !ctx->current->layout || !text)
22161  return;
22162 
22163  /* fetch configuration data */
22164  style = &ctx->style;
22165  padding = style->window.padding;
22166 
22167  /* calculate size of the text and tooltip */
22168  text_len = nk_strlen(text);
22169  text_width = style->font->width(style->font->userdata,
22170  style->font->height, text, text_len);
22171  text_width += (4 * padding.x);
22172  text_height = (style->font->height + 2 * padding.y);
22173 
22174  /* execute tooltip and fill with text */
22175  if (nk_tooltip_begin(ctx, (float)text_width)) {
22176  nk_layout_row_dynamic(ctx, (float)text_height, 1);
22177  nk_text(ctx, text, text_len, NK_TEXT_LEFT);
22178  nk_tooltip_end(ctx);
22179  }
22180 }
22181 /* -------------------------------------------------------------
22182  *
22183  * CONTEXTUAL
22184  *
22185  * -------------------------------------------------------------- */
22186 NK_API int
22187 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
22188  struct nk_rect trigger_bounds)
22189 {
22190  struct nk_window *win;
22191  struct nk_window *popup;
22192  struct nk_rect body;
22193 
22194  NK_STORAGE const struct nk_rect null_rect = {0,0,0,0};
22195  int is_clicked = 0;
22196  int is_active = 0;
22197  int is_open = 0;
22198  int ret = 0;
22199 
22200  NK_ASSERT(ctx);
22201  NK_ASSERT(ctx->current);
22202  NK_ASSERT(ctx->current->layout);
22203  if (!ctx || !ctx->current || !ctx->current->layout)
22204  return 0;
22205 
22206  win = ctx->current;
22207  ++win->popup.con_count;
22208 
22209  /* check if currently active contextual is active */
22210  popup = win->popup.win;
22211  is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
22212  is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
22213  if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
22214  return 0;
22215  if ((is_clicked && is_open && !is_active) || (!is_open && !is_active && !is_clicked))
22216  return 0;
22217 
22218  /* calculate contextual position on click */
22219  win->popup.active_con = win->popup.con_count;
22220  if (is_clicked) {
22221  body.x = ctx->input.mouse.pos.x;
22222  body.y = ctx->input.mouse.pos.y;
22223  } else {
22224  body.x = popup->bounds.x;
22225  body.y = popup->bounds.y;
22226  }
22227  body.w = size.x;
22228  body.h = size.y;
22229 
22230  /* start nonblocking contextual popup */
22231  ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
22232  null_rect, NK_PANEL_CONTEXTUAL);
22233  if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
22234  else {
22235  win->popup.active_con = 0;
22236  if (win->popup.win)
22237  win->popup.win->flags = 0;
22238  }
22239  return ret;
22240 }
22241 
22242 NK_API int
22243 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
22244  nk_flags alignment)
22245 {
22246  struct nk_window *win;
22247  const struct nk_input *in;
22248  const struct nk_style *style;
22249 
22250  struct nk_rect bounds;
22251  enum nk_widget_layout_states state;
22252 
22253  NK_ASSERT(ctx);
22254  NK_ASSERT(ctx->current);
22255  NK_ASSERT(ctx->current->layout);
22256  if (!ctx || !ctx->current || !ctx->current->layout)
22257  return 0;
22258 
22259  win = ctx->current;
22260  style = &ctx->style;
22261  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22262  if (!state) return nk_false;
22263 
22264  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22265  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
22266  text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
22267  nk_contextual_close(ctx);
22268  return nk_true;
22269  }
22270  return nk_false;
22271 }
22272 
22273 NK_API int nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
22274 {return nk_contextual_item_text(ctx, label, nk_strlen(label), align);}
22275 
22276 NK_API int
22277 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
22278  const char *text, int len, nk_flags align)
22279 {
22280  struct nk_window *win;
22281  const struct nk_input *in;
22282  const struct nk_style *style;
22283 
22284  struct nk_rect bounds;
22285  enum nk_widget_layout_states state;
22286 
22287  NK_ASSERT(ctx);
22288  NK_ASSERT(ctx->current);
22289  NK_ASSERT(ctx->current->layout);
22290  if (!ctx || !ctx->current || !ctx->current->layout)
22291  return 0;
22292 
22293  win = ctx->current;
22294  style = &ctx->style;
22295  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22296  if (!state) return nk_false;
22297 
22298  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22299  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
22300  img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
22301  nk_contextual_close(ctx);
22302  return nk_true;
22303  }
22304  return nk_false;
22305 }
22306 
22307 NK_API int nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
22308  const char *label, nk_flags align)
22309 {return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);}
22310 
22311 NK_API int
22313  const char *text, int len, nk_flags align)
22314 {
22315  struct nk_window *win;
22316  const struct nk_input *in;
22317  const struct nk_style *style;
22318 
22319  struct nk_rect bounds;
22320  enum nk_widget_layout_states state;
22321 
22322  NK_ASSERT(ctx);
22323  NK_ASSERT(ctx->current);
22324  NK_ASSERT(ctx->current->layout);
22325  if (!ctx || !ctx->current || !ctx->current->layout)
22326  return 0;
22327 
22328  win = ctx->current;
22329  style = &ctx->style;
22330  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22331  if (!state) return nk_false;
22332 
22333  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22334  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
22335  symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
22336  nk_contextual_close(ctx);
22337  return nk_true;
22338  }
22339  return nk_false;
22340 }
22341 
22343  const char *text, nk_flags align)
22344 {return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);}
22345 
22346 NK_API void
22347 nk_contextual_close(struct nk_context *ctx)
22348 {
22349  NK_ASSERT(ctx);
22350  NK_ASSERT(ctx->current);
22351  NK_ASSERT(ctx->current->layout);
22352  if (!ctx || !ctx->current || !ctx->current->layout) return;
22353  nk_popup_close(ctx);
22354 }
22355 
22356 NK_API void
22357 nk_contextual_end(struct nk_context *ctx)
22358 {
22359  struct nk_window *popup;
22360  struct nk_panel *panel;
22361  NK_ASSERT(ctx);
22362  NK_ASSERT(ctx->current);
22363  if (!ctx || !ctx->current) return;
22364 
22365  popup = ctx->current;
22366  panel = popup->layout;
22367  NK_ASSERT(popup->parent);
22368  NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
22369  if (panel->flags & NK_WINDOW_DYNAMIC) {
22370  /* Close behavior
22371  This is a bit hack solution since we do not now before we end our popup
22372  how big it will be. We therefore do not directly know when a
22373  click outside the non-blocking popup must close it at that direct frame.
22374  Instead it will be closed in the next frame.*/
22375  struct nk_rect body = {0,0,0,0};
22376  if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
22377  struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
22378  body = panel->bounds;
22379  body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
22380  body.h = (panel->bounds.y + panel->bounds.h) - body.y;
22381  }
22382 
22383  {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
22384  int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
22385  if (pressed && in_body)
22386  popup->flags |= NK_WINDOW_HIDDEN;
22387  }
22388  }
22389  if (popup->flags & NK_WINDOW_HIDDEN)
22390  popup->seq = 0;
22391  nk_popup_end(ctx);
22392  return;
22393 }
22394 /* -------------------------------------------------------------
22395  *
22396  * COMBO
22397  *
22398  * --------------------------------------------------------------*/
22399 NK_INTERN int
22400 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
22401  struct nk_vec2 size, int is_clicked, struct nk_rect header)
22402 {
22403  struct nk_window *popup;
22404  int is_open = 0;
22405  int is_active = 0;
22406  struct nk_rect body;
22407  nk_hash hash;
22408 
22409  NK_ASSERT(ctx);
22410  NK_ASSERT(ctx->current);
22411  NK_ASSERT(ctx->current->layout);
22412  if (!ctx || !ctx->current || !ctx->current->layout)
22413  return 0;
22414 
22415  popup = win->popup.win;
22416  body.x = header.x;
22417  body.w = size.x;
22418  body.y = header.y + header.h-ctx->style.window.combo_border;
22419  body.h = size.y;
22420 
22421  hash = win->popup.combo_count++;
22422  is_open = (popup) ? nk_true:nk_false;
22423  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
22424  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
22425  (!is_open && !is_active && !is_clicked)) return 0;
22426  if (!nk_nonblock_begin(ctx, 0, body,
22427  (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
22428 
22429  win->popup.type = NK_PANEL_COMBO;
22430  win->popup.name = hash;
22431  return 1;
22432 }
22433 
22434 NK_API int
22435 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
22436  struct nk_vec2 size)
22437 {
22438  const struct nk_input *in;
22439  struct nk_window *win;
22440  struct nk_style *style;
22441 
22442  enum nk_widget_layout_states s;
22443  int is_clicked = nk_false;
22444  struct nk_rect header;
22445  const struct nk_style_item *background;
22446  struct nk_text text;
22447 
22448  NK_ASSERT(ctx);
22449  NK_ASSERT(selected);
22450  NK_ASSERT(ctx->current);
22451  NK_ASSERT(ctx->current->layout);
22452  if (!ctx || !ctx->current || !ctx->current->layout || !selected)
22453  return 0;
22454 
22455  win = ctx->current;
22456  style = &ctx->style;
22457  s = nk_widget(&header, ctx);
22458  if (s == NK_WIDGET_INVALID)
22459  return 0;
22460 
22461  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22462  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22463  is_clicked = nk_true;
22464 
22465  /* draw combo box header background and border */
22466  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22467  background = &style->combo.active;
22468  text.text = style->combo.label_active;
22469  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22470  background = &style->combo.hover;
22471  text.text = style->combo.label_hover;
22472  } else {
22473  background = &style->combo.normal;
22474  text.text = style->combo.label_normal;
22475  }
22476  if (background->type == NK_STYLE_ITEM_IMAGE) {
22477  text.background = nk_rgba(0,0,0,0);
22478  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22479  } else {
22480  text.background = background->data.color;
22481  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22482  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22483  }
22484  {
22485  /* print currently selected text item */
22486  struct nk_rect label;
22487  struct nk_rect button;
22488  struct nk_rect content;
22489 
22490  enum nk_symbol_type sym;
22491  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22492  sym = style->combo.sym_hover;
22493  else if (is_clicked)
22494  sym = style->combo.sym_active;
22495  else sym = style->combo.sym_normal;
22496 
22497  /* calculate button */
22498  button.w = header.h - 2 * style->combo.button_padding.y;
22499  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22500  button.y = header.y + style->combo.button_padding.y;
22501  button.h = button.w;
22502 
22503  content.x = button.x + style->combo.button.padding.x;
22504  content.y = button.y + style->combo.button.padding.y;
22505  content.w = button.w - 2 * style->combo.button.padding.x;
22506  content.h = button.h - 2 * style->combo.button.padding.y;
22507 
22508  /* draw selected label */
22509  text.padding = nk_vec2(0,0);
22510  label.x = header.x + style->combo.content_padding.x;
22511  label.y = header.y + style->combo.content_padding.y;
22512  label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
22513  label.h = header.h - 2 * style->combo.content_padding.y;
22514  nk_widget_text(&win->buffer, label, selected, len, &text,
22515  NK_TEXT_LEFT, ctx->style.font);
22516 
22517  /* draw open/close button */
22518  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22519  &ctx->style.combo.button, sym, style->font);
22520  }
22521  return nk_combo_begin(ctx, win, size, is_clicked, header);
22522 }
22523 
22524 NK_API int nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
22525 {return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);}
22526 
22527 NK_API int
22528 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
22529 {
22530  struct nk_window *win;
22531  struct nk_style *style;
22532  const struct nk_input *in;
22533 
22534  struct nk_rect header;
22535  int is_clicked = nk_false;
22536  enum nk_widget_layout_states s;
22537  const struct nk_style_item *background;
22538 
22539  NK_ASSERT(ctx);
22540  NK_ASSERT(ctx->current);
22541  NK_ASSERT(ctx->current->layout);
22542  if (!ctx || !ctx->current || !ctx->current->layout)
22543  return 0;
22544 
22545  win = ctx->current;
22546  style = &ctx->style;
22547  s = nk_widget(&header, ctx);
22548  if (s == NK_WIDGET_INVALID)
22549  return 0;
22550 
22551  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22552  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22553  is_clicked = nk_true;
22554 
22555  /* draw combo box header background and border */
22556  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
22557  background = &style->combo.active;
22558  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22559  background = &style->combo.hover;
22560  else background = &style->combo.normal;
22561 
22562  if (background->type == NK_STYLE_ITEM_IMAGE) {
22563  nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
22564  } else {
22565  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22566  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22567  }
22568  {
22569  struct nk_rect content;
22570  struct nk_rect button;
22571  struct nk_rect bounds;
22572 
22573  enum nk_symbol_type sym;
22574  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22575  sym = style->combo.sym_hover;
22576  else if (is_clicked)
22577  sym = style->combo.sym_active;
22578  else sym = style->combo.sym_normal;
22579 
22580  /* calculate button */
22581  button.w = header.h - 2 * style->combo.button_padding.y;
22582  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22583  button.y = header.y + style->combo.button_padding.y;
22584  button.h = button.w;
22585 
22586  content.x = button.x + style->combo.button.padding.x;
22587  content.y = button.y + style->combo.button.padding.y;
22588  content.w = button.w - 2 * style->combo.button.padding.x;
22589  content.h = button.h - 2 * style->combo.button.padding.y;
22590 
22591  /* draw color */
22592  bounds.h = header.h - 4 * style->combo.content_padding.y;
22593  bounds.y = header.y + 2 * style->combo.content_padding.y;
22594  bounds.x = header.x + 2 * style->combo.content_padding.x;
22595  bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
22596  nk_fill_rect(&win->buffer, bounds, 0, color);
22597 
22598  /* draw open/close button */
22599  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22600  &ctx->style.combo.button, sym, style->font);
22601  }
22602  return nk_combo_begin(ctx, win, size, is_clicked, header);
22603 }
22604 
22605 NK_API int
22606 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
22607 {
22608  struct nk_window *win;
22609  struct nk_style *style;
22610  const struct nk_input *in;
22611 
22612  struct nk_rect header;
22613  int is_clicked = nk_false;
22614  enum nk_widget_layout_states s;
22615  const struct nk_style_item *background;
22616  struct nk_color sym_background;
22617  struct nk_color symbol_color;
22618 
22619  NK_ASSERT(ctx);
22620  NK_ASSERT(ctx->current);
22621  NK_ASSERT(ctx->current->layout);
22622  if (!ctx || !ctx->current || !ctx->current->layout)
22623  return 0;
22624 
22625  win = ctx->current;
22626  style = &ctx->style;
22627  s = nk_widget(&header, ctx);
22628  if (s == NK_WIDGET_INVALID)
22629  return 0;
22630 
22631  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22632  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22633  is_clicked = nk_true;
22634 
22635  /* draw combo box header background and border */
22636  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22637  background = &style->combo.active;
22638  symbol_color = style->combo.symbol_active;
22639  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22640  background = &style->combo.hover;
22641  symbol_color = style->combo.symbol_hover;
22642  } else {
22643  background = &style->combo.normal;
22644  symbol_color = style->combo.symbol_hover;
22645  }
22646 
22647  if (background->type == NK_STYLE_ITEM_IMAGE) {
22648  sym_background = nk_rgba(0,0,0,0);
22649  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22650  } else {
22651  sym_background = background->data.color;
22652  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22653  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22654  }
22655  {
22656  struct nk_rect bounds = {0,0,0,0};
22657  struct nk_rect content;
22658  struct nk_rect button;
22659 
22660  enum nk_symbol_type sym;
22661  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22662  sym = style->combo.sym_hover;
22663  else if (is_clicked)
22664  sym = style->combo.sym_active;
22665  else sym = style->combo.sym_normal;
22666 
22667  /* calculate button */
22668  button.w = header.h - 2 * style->combo.button_padding.y;
22669  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
22670  button.y = header.y + style->combo.button_padding.y;
22671  button.h = button.w;
22672 
22673  content.x = button.x + style->combo.button.padding.x;
22674  content.y = button.y + style->combo.button.padding.y;
22675  content.w = button.w - 2 * style->combo.button.padding.x;
22676  content.h = button.h - 2 * style->combo.button.padding.y;
22677 
22678  /* draw symbol */
22679  bounds.h = header.h - 2 * style->combo.content_padding.y;
22680  bounds.y = header.y + style->combo.content_padding.y;
22681  bounds.x = header.x + style->combo.content_padding.x;
22682  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
22683  nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
22684  1.0f, style->font);
22685 
22686  /* draw open/close button */
22687  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
22688  &ctx->style.combo.button, sym, style->font);
22689  }
22690  return nk_combo_begin(ctx, win, size, is_clicked, header);
22691 }
22692 
22693 NK_API int
22694 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
22695  enum nk_symbol_type symbol, struct nk_vec2 size)
22696 {
22697  struct nk_window *win;
22698  struct nk_style *style;
22699  struct nk_input *in;
22700 
22701  struct nk_rect header;
22702  int is_clicked = nk_false;
22703  enum nk_widget_layout_states s;
22704  const struct nk_style_item *background;
22705  struct nk_color symbol_color;
22706  struct nk_text text;
22707 
22708  NK_ASSERT(ctx);
22709  NK_ASSERT(ctx->current);
22710  NK_ASSERT(ctx->current->layout);
22711  if (!ctx || !ctx->current || !ctx->current->layout)
22712  return 0;
22713 
22714  win = ctx->current;
22715  style = &ctx->style;
22716  s = nk_widget(&header, ctx);
22717  if (!s) return 0;
22718 
22719  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22720  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22721  is_clicked = nk_true;
22722 
22723  /* draw combo box header background and border */
22724  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22725  background = &style->combo.active;
22726  symbol_color = style->combo.symbol_active;
22727  text.text = style->combo.label_active;
22728  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22729  background = &style->combo.hover;
22730  symbol_color = style->combo.symbol_hover;
22731  text.text = style->combo.label_hover;
22732  } else {
22733  background = &style->combo.normal;
22734  symbol_color = style->combo.symbol_normal;
22735  text.text = style->combo.label_normal;
22736  }
22737  if (background->type == NK_STYLE_ITEM_IMAGE) {
22738  text.background = nk_rgba(0,0,0,0);
22739  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22740  } else {
22741  text.background = background->data.color;
22742  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22743  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22744  }
22745  {
22746  struct nk_rect content;
22747  struct nk_rect button;
22748  struct nk_rect label;
22749  struct nk_rect image;
22750 
22751  enum nk_symbol_type sym;
22752  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22753  sym = style->combo.sym_hover;
22754  else if (is_clicked)
22755  sym = style->combo.sym_active;
22756  else sym = style->combo.sym_normal;
22757 
22758  /* calculate button */
22759  button.w = header.h - 2 * style->combo.button_padding.y;
22760  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22761  button.y = header.y + style->combo.button_padding.y;
22762  button.h = button.w;
22763 
22764  content.x = button.x + style->combo.button.padding.x;
22765  content.y = button.y + style->combo.button.padding.y;
22766  content.w = button.w - 2 * style->combo.button.padding.x;
22767  content.h = button.h - 2 * style->combo.button.padding.y;
22768  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22769  &ctx->style.combo.button, sym, style->font);
22770 
22771  /* draw symbol */
22772  image.x = header.x + style->combo.content_padding.x;
22773  image.y = header.y + style->combo.content_padding.y;
22774  image.h = header.h - 2 * style->combo.content_padding.y;
22775  image.w = image.h;
22776  nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
22777  1.0f, style->font);
22778 
22779  /* draw label */
22780  text.padding = nk_vec2(0,0);
22781  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
22782  label.y = header.y + style->combo.content_padding.y;
22783  label.w = (button.x - style->combo.content_padding.x) - label.x;
22784  label.h = header.h - 2 * style->combo.content_padding.y;
22785  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
22786  }
22787  return nk_combo_begin(ctx, win, size, is_clicked, header);
22788 }
22789 
22790 NK_API int
22791 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
22792 {
22793  struct nk_window *win;
22794  struct nk_style *style;
22795  const struct nk_input *in;
22796 
22797  struct nk_rect header;
22798  int is_clicked = nk_false;
22799  enum nk_widget_layout_states s;
22800  const struct nk_style_item *background;
22801 
22802  NK_ASSERT(ctx);
22803  NK_ASSERT(ctx->current);
22804  NK_ASSERT(ctx->current->layout);
22805  if (!ctx || !ctx->current || !ctx->current->layout)
22806  return 0;
22807 
22808  win = ctx->current;
22809  style = &ctx->style;
22810  s = nk_widget(&header, ctx);
22811  if (s == NK_WIDGET_INVALID)
22812  return 0;
22813 
22814  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22815  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22816  is_clicked = nk_true;
22817 
22818  /* draw combo box header background and border */
22819  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
22820  background = &style->combo.active;
22821  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22822  background = &style->combo.hover;
22823  else background = &style->combo.normal;
22824 
22825  if (background->type == NK_STYLE_ITEM_IMAGE) {
22826  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22827  } else {
22828  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22829  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22830  }
22831  {
22832  struct nk_rect bounds = {0,0,0,0};
22833  struct nk_rect content;
22834  struct nk_rect button;
22835 
22836  enum nk_symbol_type sym;
22837  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22838  sym = style->combo.sym_hover;
22839  else if (is_clicked)
22840  sym = style->combo.sym_active;
22841  else sym = style->combo.sym_normal;
22842 
22843  /* calculate button */
22844  button.w = header.h - 2 * style->combo.button_padding.y;
22845  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
22846  button.y = header.y + style->combo.button_padding.y;
22847  button.h = button.w;
22848 
22849  content.x = button.x + style->combo.button.padding.x;
22850  content.y = button.y + style->combo.button.padding.y;
22851  content.w = button.w - 2 * style->combo.button.padding.x;
22852  content.h = button.h - 2 * style->combo.button.padding.y;
22853 
22854  /* draw image */
22855  bounds.h = header.h - 2 * style->combo.content_padding.y;
22856  bounds.y = header.y + style->combo.content_padding.y;
22857  bounds.x = header.x + style->combo.content_padding.x;
22858  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
22859  nk_draw_image(&win->buffer, bounds, &img, nk_white);
22860 
22861  /* draw open/close button */
22862  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
22863  &ctx->style.combo.button, sym, style->font);
22864  }
22865  return nk_combo_begin(ctx, win, size, is_clicked, header);
22866 }
22867 
22868 NK_API int
22869 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
22870  struct nk_image img, struct nk_vec2 size)
22871 {
22872  struct nk_window *win;
22873  struct nk_style *style;
22874  struct nk_input *in;
22875 
22876  struct nk_rect header;
22877  int is_clicked = nk_false;
22878  enum nk_widget_layout_states s;
22879  const struct nk_style_item *background;
22880  struct nk_text text;
22881 
22882  NK_ASSERT(ctx);
22883  NK_ASSERT(ctx->current);
22884  NK_ASSERT(ctx->current->layout);
22885  if (!ctx || !ctx->current || !ctx->current->layout)
22886  return 0;
22887 
22888  win = ctx->current;
22889  style = &ctx->style;
22890  s = nk_widget(&header, ctx);
22891  if (!s) return 0;
22892 
22893  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22894  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22895  is_clicked = nk_true;
22896 
22897  /* draw combo box header background and border */
22898  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22899  background = &style->combo.active;
22900  text.text = style->combo.label_active;
22901  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22902  background = &style->combo.hover;
22903  text.text = style->combo.label_hover;
22904  } else {
22905  background = &style->combo.normal;
22906  text.text = style->combo.label_normal;
22907  }
22908  if (background->type == NK_STYLE_ITEM_IMAGE) {
22909  text.background = nk_rgba(0,0,0,0);
22910  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22911  } else {
22912  text.background = background->data.color;
22913  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22914  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22915  }
22916  {
22917  struct nk_rect content;
22918  struct nk_rect button;
22919  struct nk_rect label;
22920  struct nk_rect image;
22921 
22922  enum nk_symbol_type sym;
22923  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22924  sym = style->combo.sym_hover;
22925  else if (is_clicked)
22926  sym = style->combo.sym_active;
22927  else sym = style->combo.sym_normal;
22928 
22929  /* calculate button */
22930  button.w = header.h - 2 * style->combo.button_padding.y;
22931  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22932  button.y = header.y + style->combo.button_padding.y;
22933  button.h = button.w;
22934 
22935  content.x = button.x + style->combo.button.padding.x;
22936  content.y = button.y + style->combo.button.padding.y;
22937  content.w = button.w - 2 * style->combo.button.padding.x;
22938  content.h = button.h - 2 * style->combo.button.padding.y;
22939  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22940  &ctx->style.combo.button, sym, style->font);
22941 
22942  /* draw image */
22943  image.x = header.x + style->combo.content_padding.x;
22944  image.y = header.y + style->combo.content_padding.y;
22945  image.h = header.h - 2 * style->combo.content_padding.y;
22946  image.w = image.h;
22947  nk_draw_image(&win->buffer, image, &img, nk_white);
22948 
22949  /* draw label */
22950  text.padding = nk_vec2(0,0);
22951  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
22952  label.y = header.y + style->combo.content_padding.y;
22953  label.w = (button.x - style->combo.content_padding.x) - label.x;
22954  label.h = header.h - 2 * style->combo.content_padding.y;
22955  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
22956  }
22957  return nk_combo_begin(ctx, win, size, is_clicked, header);
22958 }
22959 
22961  const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
22962 {return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);}
22963 
22965  const char *selected, struct nk_image img, struct nk_vec2 size)
22966 {return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);}
22967 
22968 NK_API int nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
22969 {return nk_contextual_item_text(ctx, text, len, align);}
22970 
22971 NK_API int nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
22972 {return nk_contextual_item_label(ctx, label, align);}
22973 
22974 NK_API int nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
22975  int len, nk_flags alignment)
22976 {return nk_contextual_item_image_text(ctx, img, text, len, alignment);}
22977 
22978 NK_API int nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
22979  const char *text, nk_flags alignment)
22980 {return nk_contextual_item_image_label(ctx, img, text, alignment);}
22981 
22982 NK_API int nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
22983  const char *text, int len, nk_flags alignment)
22984 {return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);}
22985 
22987  const char *label, nk_flags alignment)
22988 {return nk_contextual_item_symbol_label(ctx, sym, label, alignment);}
22989 
22990 NK_API void nk_combo_end(struct nk_context *ctx)
22991 {nk_contextual_end(ctx);}
22992 
22993 NK_API void nk_combo_close(struct nk_context *ctx)
22994 {nk_contextual_close(ctx);}
22995 
22996 NK_API int
22997 nk_combo(struct nk_context *ctx, const char **items, int count,
22998  int selected, int item_height, struct nk_vec2 size)
22999 {
23000  int i = 0;
23001  int max_height;
23002  struct nk_vec2 item_spacing;
23003  struct nk_vec2 window_padding;
23004 
23005  NK_ASSERT(ctx);
23006  NK_ASSERT(items);
23007  NK_ASSERT(ctx->current);
23008  if (!ctx || !items ||!count)
23009  return selected;
23010 
23011  item_spacing = ctx->style.window.spacing;
23012  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23013  max_height = count * item_height + count * (int)item_spacing.y;
23014  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23015  size.y = NK_MIN(size.y, (float)max_height);
23016  if (nk_combo_begin_label(ctx, items[selected], size)) {
23017  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23018  for (i = 0; i < count; ++i) {
23019  if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
23020  selected = i;
23021  }
23022  nk_combo_end(ctx);
23023  }
23024  return selected;
23025 }
23026 
23027 NK_API int
23028 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
23029  int separator, int selected, int count, int item_height, struct nk_vec2 size)
23030 {
23031  int i;
23032  int max_height;
23033  struct nk_vec2 item_spacing;
23034  struct nk_vec2 window_padding;
23035  const char *current_item;
23036  const char *iter;
23037  int length = 0;
23038 
23039  NK_ASSERT(ctx);
23040  NK_ASSERT(items_separated_by_separator);
23041  if (!ctx || !items_separated_by_separator)
23042  return selected;
23043 
23044  /* calculate popup window */
23045  item_spacing = ctx->style.window.spacing;
23046  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23047  max_height = count * item_height + count * (int)item_spacing.y;
23048  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23049  size.y = NK_MIN(size.y, (float)max_height);
23050 
23051  /* find selected item */
23052  current_item = items_separated_by_separator;
23053  for (i = 0; i < count; ++i) {
23054  iter = current_item;
23055  while (*iter && *iter != separator) iter++;
23056  length = (int)(iter - current_item);
23057  if (i == selected) break;
23058  current_item = iter + 1;
23059  }
23060 
23061  if (nk_combo_begin_text(ctx, current_item, length, size)) {
23062  current_item = items_separated_by_separator;
23063  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23064  for (i = 0; i < count; ++i) {
23065  iter = current_item;
23066  while (*iter && *iter != separator) iter++;
23067  length = (int)(iter - current_item);
23068  if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
23069  selected = i;
23070  current_item = current_item + length + 1;
23071  }
23072  nk_combo_end(ctx);
23073  }
23074  return selected;
23075 }
23076 
23077 NK_API int
23078 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
23079  int selected, int count, int item_height, struct nk_vec2 size)
23080 {return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);}
23081 
23082 NK_API int
23083 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
23084  void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
23085 {
23086  int i;
23087  int max_height;
23088  struct nk_vec2 item_spacing;
23089  struct nk_vec2 window_padding;
23090  const char *item;
23091 
23092  NK_ASSERT(ctx);
23093  NK_ASSERT(item_getter);
23094  if (!ctx || !item_getter)
23095  return selected;
23096 
23097  /* calculate popup window */
23098  item_spacing = ctx->style.window.spacing;
23099  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23100  max_height = count * item_height + count * (int)item_spacing.y;
23101  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23102  size.y = NK_MIN(size.y, (float)max_height);
23103 
23104  item_getter(userdata, selected, &item);
23105  if (nk_combo_begin_label(ctx, item, size)) {
23106  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23107  for (i = 0; i < count; ++i) {
23108  item_getter(userdata, i, &item);
23109  if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
23110  selected = i;
23111  }
23112  nk_combo_end(ctx);
23113  }
23114  return selected;
23115 }
23116 
23117 NK_API void nk_combobox(struct nk_context *ctx, const char **items, int count,
23118  int *selected, int item_height, struct nk_vec2 size)
23119 {*selected = nk_combo(ctx, items, count, *selected, item_height, size);}
23120 
23121 NK_API void nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
23122  int *selected, int count, int item_height, struct nk_vec2 size)
23123 {*selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);}
23124 
23125 NK_API void nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
23126  int separator,int *selected, int count, int item_height, struct nk_vec2 size)
23127 {*selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
23128  *selected, count, item_height, size);}
23129 
23130 NK_API void nk_combobox_callback(struct nk_context *ctx,
23131  void(*item_getter)(void* data, int id, const char **out_text),
23132  void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
23133 {*selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size);}
23134 
23135 /*
23136  * -------------------------------------------------------------
23137  *
23138  * MENU
23139  *
23140  * --------------------------------------------------------------
23141  */
23142 NK_INTERN int
23143 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
23144  const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
23145 {
23146  int is_open = 0;
23147  int is_active = 0;
23148  struct nk_rect body;
23149  struct nk_window *popup;
23150  nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
23151 
23152  NK_ASSERT(ctx);
23153  NK_ASSERT(ctx->current);
23154  NK_ASSERT(ctx->current->layout);
23155  if (!ctx || !ctx->current || !ctx->current->layout)
23156  return 0;
23157 
23158  body.x = header.x;
23159  body.w = size.x;
23160  body.y = header.y + header.h;
23161  body.h = size.y;
23162 
23163  popup = win->popup.win;
23164  is_open = popup ? nk_true : nk_false;
23165  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
23166  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
23167  (!is_open && !is_active && !is_clicked)) return 0;
23168  if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
23169  return 0;
23170 
23171  win->popup.type = NK_PANEL_MENU;
23172  win->popup.name = hash;
23173  return 1;
23174 }
23175 
23176 NK_API int
23177 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
23178  nk_flags align, struct nk_vec2 size)
23179 {
23180  struct nk_window *win;
23181  const struct nk_input *in;
23182  struct nk_rect header;
23183  int is_clicked = nk_false;
23184  nk_flags state;
23185 
23186  NK_ASSERT(ctx);
23187  NK_ASSERT(ctx->current);
23188  NK_ASSERT(ctx->current->layout);
23189  if (!ctx || !ctx->current || !ctx->current->layout)
23190  return 0;
23191 
23192  win = ctx->current;
23193  state = nk_widget(&header, ctx);
23194  if (!state) return 0;
23195  in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23196  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
23197  title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
23198  is_clicked = nk_true;
23199  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23200 }
23201 
23202 NK_API int nk_menu_begin_label(struct nk_context *ctx,
23203  const char *text, nk_flags align, struct nk_vec2 size)
23204 {return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);}
23205 
23206 NK_API int
23207 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
23208  struct nk_vec2 size)
23209 {
23210  struct nk_window *win;
23211  struct nk_rect header;
23212  const struct nk_input *in;
23213  int is_clicked = nk_false;
23214  nk_flags state;
23215 
23216  NK_ASSERT(ctx);
23217  NK_ASSERT(ctx->current);
23218  NK_ASSERT(ctx->current->layout);
23219  if (!ctx || !ctx->current || !ctx->current->layout)
23220  return 0;
23221 
23222  win = ctx->current;
23223  state = nk_widget(&header, ctx);
23224  if (!state) return 0;
23225  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23226  if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
23227  img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
23228  is_clicked = nk_true;
23229  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
23230 }
23231 
23232 NK_API int
23233 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
23234  enum nk_symbol_type sym, struct nk_vec2 size)
23235 {
23236  struct nk_window *win;
23237  const struct nk_input *in;
23238  struct nk_rect header;
23239  int is_clicked = nk_false;
23240  nk_flags state;
23241 
23242  NK_ASSERT(ctx);
23243  NK_ASSERT(ctx->current);
23244  NK_ASSERT(ctx->current->layout);
23245  if (!ctx || !ctx->current || !ctx->current->layout)
23246  return 0;
23247 
23248  win = ctx->current;
23249  state = nk_widget(&header, ctx);
23250  if (!state) return 0;
23251  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23252  if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header,
23253  sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
23254  is_clicked = nk_true;
23255  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
23256 }
23257 
23258 NK_API int
23259 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
23260  nk_flags align, struct nk_image img, struct nk_vec2 size)
23261 {
23262  struct nk_window *win;
23263  struct nk_rect header;
23264  const struct nk_input *in;
23265  int is_clicked = nk_false;
23266  nk_flags state;
23267 
23268  NK_ASSERT(ctx);
23269  NK_ASSERT(ctx->current);
23270  NK_ASSERT(ctx->current->layout);
23271  if (!ctx || !ctx->current || !ctx->current->layout)
23272  return 0;
23273 
23274  win = ctx->current;
23275  state = nk_widget(&header, ctx);
23276  if (!state) return 0;
23277  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23278  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
23279  header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
23280  ctx->style.font, in))
23281  is_clicked = nk_true;
23282  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23283 }
23284 
23286  const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
23287 {return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);}
23288 
23289 NK_API int
23290 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
23291  nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
23292 {
23293  struct nk_window *win;
23294  struct nk_rect header;
23295  const struct nk_input *in;
23296  int is_clicked = nk_false;
23297  nk_flags state;
23298 
23299  NK_ASSERT(ctx);
23300  NK_ASSERT(ctx->current);
23301  NK_ASSERT(ctx->current->layout);
23302  if (!ctx || !ctx->current || !ctx->current->layout)
23303  return 0;
23304 
23305  win = ctx->current;
23306  state = nk_widget(&header, ctx);
23307  if (!state) return 0;
23308 
23309  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23310  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
23311  header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
23312  ctx->style.font, in)) is_clicked = nk_true;
23313  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23314 }
23315 
23317  const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
23318 {return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);}
23319 
23320 NK_API int nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
23321 {return nk_contextual_item_text(ctx, title, len, align);}
23322 
23323 NK_API int nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
23324 {return nk_contextual_item_label(ctx, label, align);}
23325 
23326 NK_API int nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
23327  const char *label, nk_flags align)
23328 {return nk_contextual_item_image_label(ctx, img, label, align);}
23329 
23330 NK_API int nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
23331  const char *text, int len, nk_flags align)
23332 {return nk_contextual_item_image_text(ctx, img, text, len, align);}
23333 
23334 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
23335  const char *text, int len, nk_flags align)
23336 {return nk_contextual_item_symbol_text(ctx, sym, text, len, align);}
23337 
23338 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
23339  const char *label, nk_flags align)
23340 {return nk_contextual_item_symbol_label(ctx, sym, label, align);}
23341 
23342 NK_API void nk_menu_close(struct nk_context *ctx)
23343 {nk_contextual_close(ctx);}
23344 
23345 NK_API void
23346 nk_menu_end(struct nk_context *ctx)
23347 {nk_contextual_end(ctx);}
23348 
23349 #endif
Definition: nuklear.h:1901
unsigned short r
Definition: nuklear.h:2943
struct nk_vec2 padding
Definition: nuklear.h:3506
Definition: nuklear.h:3006
Definition: nuklear.h:2026
NK_API struct nk_color nk_rgb_iv(const int *rgb)
struct nk_command header
Definition: nuklear.h:2856
Definition: nuklear.h:689
short cx
Definition: nuklear.h:2942
NK_API int nk_menu_item_text(struct nk_context *, const char *, int, nk_flags align)
struct nk_style_item hover
Definition: nuklear.h:3456
nk_chart_event
Definition: nuklear.h:472
struct nk_vec2 padding
Definition: nuklear.h:3412
float preferred_x
Definition: nuklear.h:2740
struct nk_style_item hover_active
Definition: nuklear.h:3328
NK_API int nk_window_has_focus(const struct nk_context *)
NK_API int nk_menu_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
Definition: nuklear.h:3725
struct nk_style_button dec_button
Definition: nuklear.h:3510
NK_API struct nk_rect nk_rectv(const float *xywh)
nk_handle userdata
Definition: nuklear.h:3415
Definition: nuklear.h:1889
#define NK_CONFIG_STACK(type, size)
Definition: nuklear.h:3929
struct nk_style_item cursor_hover
Definition: nuklear.h:3299
struct nk_command header
Definition: nuklear.h:2909
NK_API int nk_input_mouse_clicked(const struct nk_input *, enum nk_buttons, struct nk_rect)
struct nk_pool pool
Definition: nuklear.h:4035
struct nk_style_item active
Definition: nuklear.h:3359
NK_API int nk_select_text(struct nk_context *, const char *, int, nk_flags align, int value)
NK_API int nk_tree_state_image_push(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state)
unsigned int scrolled
Definition: nuklear.h:3859
NK_API void nk_window_set_position(struct nk_context *, struct nk_vec2 pos)
NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba)
float menu_border
Definition: nuklear.h:3630
NK_API int nk_contextual_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
NK_API void nk_textedit_select_all(struct nk_text_edit *)
struct nk_style_button close_button
Definition: nuklear.h:3595
Definition: nuklear.h:2940
nk_convert_result
Definition: nuklear.h:970
NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align)
NK_API int nk_contextual_begin(struct nk_context *, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds)
struct nk_vec2 last
Definition: nuklear.h:3710
struct nk_color label_normal
Definition: nuklear.h:3602
struct nk_color text_hover
Definition: nuklear.h:3333
Definition: nuklear.h:3704
Definition: nuklear.h:2931
int show_buttons
Definition: nuklear.h:3441
void * memory
Definition: nuklear.h:2537
struct nk_style_item cursor_normal
Definition: nuklear.h:3298
Definition: nuklear.h:3043
NK_API void nk_color_hex_rgb(char *output, struct nk_color)
float rounding_cursor
Definition: nuklear.h:3437
Definition: nuklear.h:2040
float border
Definition: nuklear.h:3278
float border
Definition: nuklear.h:3769
NK_API struct nk_rect nk_get_null_rect(void)
nk_buffer_allocation_type
Definition: nuklear.h:2550
NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags)
void *(* nk_plugin_alloc)(nk_handle, void *old, nk_size)
Definition: nuklear.h:478
struct nk_color color
Definition: nuklear.h:2945
#define NK_STORAGE
Definition: nuklear.h:287
nk_handle userdata
Definition: nuklear.h:3389
nk_widget_states
Definition: nuklear.h:1714
void(* nk_plugin_paste)(nk_handle, struct nk_text_edit *)
Definition: nuklear.h:481
Definition: nuklear.h:1184
float tooltip_border
Definition: nuklear.h:3632
float max_x
Definition: nuklear.h:3766
#define NK_INT32
Definition: nuklear.h:352
NK_API int nk_contextual_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API int nk_filter_default(const struct nk_text_edit *, nk_rune unicode)
unsigned int page_count
Definition: nuklear.h:3996
nk_size allocated
Definition: nuklear.h:2573
unsigned short w
Definition: nuklear.h:2892
NK_API void nk_stroke_circle(struct nk_command_buffer *, struct nk_rect, float line_thickness, struct nk_color)
NK_API struct nk_vec2 nk_vec2i(int x, int y)
Definition: nuklear.h:1183
struct nk_vec2 contextual_padding
Definition: nuklear.h:3644
Definition: nuklear.h:2041
nk_panel_flags
Definition: nuklear.h:1173
NK_API int nk_utf_decode(const char *, nk_rune *, int)
struct nk_style_button menu_button
Definition: nuklear.h:3659
Definition: nuklear.h:1895
NK_API struct nk_color nk_rgba_u32(nk_uint)
nk_size needed
Definition: nuklear.h:2575
NK_API int nk_filter_hex(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_menu_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
float bar_height
Definition: nuklear.h:3376
unsigned short w
Definition: nuklear.h:2885
NK_API void nk_buffer_init(struct nk_buffer *, const struct nk_allocator *, nk_size size)
NK_API int nk_button_color(struct nk_context *, struct nk_color)
unsigned short h
Definition: nuklear.h:2927
NK_API int nk_select_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int value)
NK_API struct nk_window * nk_window_find(struct nk_context *ctx, const char *name)
NK_API void nk_str_remove_chars(struct nk_str *, int len)
NK_API int nk_widget_is_hovered(struct nk_context *)
#define NK_FLAGS_STACK_SIZE
Definition: nuklear.h:3917
NK_API void nk_layout_row_end(struct nk_context *)
Definition: nuklear.h:2819
Definition: nuklear.h:664
NK_API void nk_fill_circle(struct nk_command_buffer *, struct nk_rect, struct nk_color)
NK_API void nk_window_set_size(struct nk_context *, struct nk_vec2)
struct nk_vec2 padding
Definition: nuklear.h:3260
#define nk_zero_struct(s)
Definition: nuklear.h:4071
struct nk_color label_active
Definition: nuklear.h:3604
struct nk_image img
Definition: nuklear.h:462
Definition: nuklear.h:3799
Definition: deflate.c:117
struct nk_color text_normal
Definition: nuklear.h:3272
Definition: nuklear.h:2552
nk_handle handle
Definition: nuklear.h:461
float border
Definition: nuklear.h:3504
Definition: nuklear.h:453
unsigned int seq
Definition: nuklear.h:3819
Definition: nuklear.h:3069
float rounding
Definition: nuklear.h:3435
Definition: nuklear.h:3696
short x
Definition: nuklear.h:2851
enum nk_symbol_type sym_left
Definition: nuklear.h:3500
struct nk_config_stack_button_behavior button_behaviors
Definition: nuklear.h:3959
nk_flags text_alignment
Definition: nuklear.h:3275
struct nk_rect clip
Definition: nuklear.h:3771
short y
Definition: nuklear.h:2891
struct config_s config
Definition: nuklear.h:670
nk_modify
Definition: nuklear.h:467
Definition: nuklear.h:484
struct nk_color selected_text_hover
Definition: nuklear.h:3476
NK_API int nk_combo_callback(struct nk_context *, void(*item_getter)(void *, int, const char **), void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down)
float y
Definition: nuklear.h:3756
short h
Definition: nuklear.h:458
NK_API void nk_str_init_fixed(struct nk_str *, void *memory, nk_size size)
Definition: nuklear.h:3817
struct nk_color col
Definition: nuklear.h:2976
NK_API int nk_popup_begin(struct nk_context *, enum nk_popup_type, const char *, nk_flags, struct nk_rect bounds)
NK_API void nk_property_float(struct nk_context *, const char *name, float min, float *val, float max, float step, float inc_per_pixel)
NK_API void nk_layout_row_template_push_variable(struct nk_context *, float min_width)
nk_style_header_align
Definition: nuklear.h:3584
struct nk_vec2 touch_padding
Definition: nuklear.h:3310
Definition: nuklear.h:1887
NK_API int nk_button_text_styled(struct nk_context *, const struct nk_style_button *, const char *title, int len)
struct nk_row_layout row
Definition: nuklear.h:3773
unsigned short line_thickness
Definition: nuklear.h:2966
unsigned int seq
Definition: nuklear.h:3969
struct nk_style_button node_maximize_button
Definition: nuklear.h:3571
NK_API void nk_layout_space_push(struct nk_context *, struct nk_rect)
NK_API void nk_layout_row_template_push_static(struct nk_context *, float width)
int cursor
Definition: nuklear.h:3834
NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color)
struct nk_vec2 tooltip_padding
Definition: nuklear.h:3646
Definition: nuklear.h:465
NK_API void nk_combobox_callback(struct nk_context *, void(*item_getter)(void *, int, const char **), void *, int *selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_combo_item_text(struct nk_context *, const char *, int, nk_flags alignment)
Definition: nuklear.h:683
NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context *, nk_flags, char *buffer, int max, nk_plugin_filter)
struct nk_window * current
Definition: nuklear.h:4039
NK_API void nk_text(struct nk_context *, const char *, int, nk_flags)
nk_flags flags
Definition: nuklear.h:3847
Definition: nuklear.h:2832
Definition: nuklear.h:3692
struct nk_color color
Definition: nuklear.h:2913
Definition: nuklear.h:3701
Definition: nuklear.h:3993
nk_uint values[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:3971
Definition: nuklear.h:1878
float border
Definition: nuklear.h:3526
NK_API int nk_select_label(struct nk_context *, const char *, nk_flags align, int value)
float h
Definition: nuklear.h:3716
NK_API int nk_menu_item_label(struct nk_context *, const char *, nk_flags alignment)
struct nk_color color
Definition: nuklear.h:2860
Definition: nuklear.h:3729
float cursor_size
Definition: nuklear.h:3481
struct nk_vec2i c
Definition: nuklear.h:2904
struct nk_color selected_text_normal
Definition: nuklear.h:3475
Definition: nuklear.h:3518
float w
Definition: nuklear.h:3716
Definition: nuklear.h:1750
NK_API int nk_button_symbol_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type)
float item_height
Definition: nuklear.h:3739
struct nk_color color
Definition: nuklear.h:2869
struct nk_chart_slot slots[NK_CHART_MAX_SLOT]
Definition: nuklear.h:3717
float border
Definition: nuklear.h:3312
struct nk_color text_normal_active
Definition: nuklear.h:3337
char nk_glyph[NK_UTF_SIZE]
Definition: nuklear.h:459
nk_plugin_free free
Definition: nuklear.h:487
NK_POINTER_TYPE nk_ptr
Definition: nuklear.h:402
NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context *, struct nk_rect)
Definition: nuklear.h:492
nk_handle texture
Definition: nuklear.h:978
Definition: nuklear.h:1678
NK_API struct nk_color nk_hsv(int h, int s, int v)
struct nk_chart chart
Definition: nuklear.h:3774
struct nk_color tooltip_border_color
Definition: nuklear.h:3624
struct nk_vec2 image_padding
Definition: nuklear.h:3347
int where
Definition: nuklear.h:2698
nk_flags text_alignment
Definition: nuklear.h:3341
struct nk_vec2 cursor_size
Definition: nuklear.h:3379
struct nk_color group_border_color
Definition: nuklear.h:3623
struct nk_style_item scaler
Definition: nuklear.h:3625
Definition: nuklear.h:1174
#define NK_ABS(a)
Definition: nuklear.h:4055
nk_buttons
Definition: nuklear.h:695
NK_API void nk_edit_focus(struct nk_context *, nk_flags flags)
Definition: nuklear.h:3747
unsigned short point_count
Definition: nuklear.h:2952
Definition: nuklear.h:476
#define NK_MAX_FLOAT_PRECISION
Definition: nuklear.h:4050
#define NK_MAX_NUMBER_BUFFER
Definition: nuklear.h:260
unsigned char ungrab
Definition: nuklear.h:3056
short insert_length
Definition: nuklear.h:2699
short x
Definition: nuklear.h:2918
Definition: nuklear.h:3721
nk_edit_types
Definition: nuklear.h:1891
NK_API struct nk_color nk_hsv_fv(const float *hsv)
NK_API struct nk_style_item nk_style_item_image(struct nk_image img)
Definition: nuklear.h:1894
nk_anti_aliasing
Definition: nuklear.h:969
NK_API int nk_widget_is_mouse_clicked(struct nk_context *, enum nk_buttons)
struct nk_color bar_hover
Definition: nuklear.h:3364
struct nk_style_progress progress
Definition: nuklear.h:3664
NK_API void nk_window_collapse(struct nk_context *, const char *name, enum nk_collapse_states state)
Definition: nuklear.h:3690
short y
Definition: nuklear.h:458
Definition: nuklear.h:2054
NK_API void nk_button_set_behavior(struct nk_context *, enum nk_button_behavior)
nk_handle userdata
Definition: nuklear.h:2692
NK_API void nk_group_end(struct nk_context *)
NK_API int nk_input_is_key_pressed(const struct nk_input *, enum nk_keys)
unsigned short point_count
Definition: nuklear.h:2959
struct nk_style_item normal
Definition: nuklear.h:3322
#define NK_FLAG(x)
Definition: nuklear.h:290
unsigned short w
Definition: nuklear.h:2877
int32_t current
Definition: netobject.cpp:37
unsigned short line_thickness
Definition: nuklear.h:2857
#define NK_UTF_INVALID
Definition: nuklear.h:4049
unsigned short h
Definition: nuklear.h:2974
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3450
struct nk_color top
Definition: nuklear.h:2894
Definition: nuklear.h:3691
struct nk_property_state property
Definition: nuklear.h:3856
NK_API void nk_layout_space_end(struct nk_context *)
#define NK_GLOBAL
Definition: nuklear.h:288
struct nk_style_item active
Definition: nuklear.h:3457
struct nk_style_item cursor_hover
Definition: nuklear.h:3370
nk_flags flags
Definition: nuklear.h:3762
struct nk_color border_color
Definition: nuklear.h:3618
struct nk_color text_pressed
Definition: nuklear.h:3334
Definition: nuklear.h:1902
NK_API void nk_layout_row_template_push_dynamic(struct nk_context *)
short y
Definition: nuklear.h:2876
float min
Definition: nuklear.h:3708
unsigned short w
Definition: nuklear.h:2974
struct nk_style_item normal
Definition: nuklear.h:3265
struct nk_page_element * freelist
Definition: nuklear.h:4040
Definition: nuklear.h:2724
Definition: nuklear.h:2889
NK_API int k_button_symbol_label_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type, const char *, nk_flags text_alignment)
struct nk_vec2i c
Definition: nuklear.h:2912
struct nk_style_selectable selectable
Definition: nuklear.h:3662
NK_API int nk_str_insert_str_runes(struct nk_str *, int pos, const nk_rune *)
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3514
enum nk_symbol_type sym_minimize
Definition: nuklear.h:3573
struct nk_style_button inc_button
Definition: nuklear.h:3383
nk_handle userdata
Definition: nuklear.h:3315
#define NK_ALIGNOF(t)
Definition: nuklear.h:4114
Definition: nuklear.h:969
struct nk_style_window window
Definition: nuklear.h:3672
float height
Definition: nuklear.h:3735
unsigned char grab
Definition: nuklear.h:3054
enum nk_symbol_type dec_symbol
Definition: nuklear.h:3445
int select_start
Definition: nuklear.h:2731
struct nk_vec2i ctrl[2]
Definition: nuklear.h:2868
float group_border
Definition: nuklear.h:3631
NK_API void nk_stroke_triangle(struct nk_command_buffer *, float, float, float, float, float, float, float line_thichness, struct nk_color)
NK_SIZE_TYPE nk_size
Definition: nuklear.h:401
unsigned short w
Definition: nuklear.h:2852
Definition: nuklear.h:3788
unsigned short line_thickness
Definition: nuklear.h:2901
struct nk_color border_color
Definition: nuklear.h:3458
struct nk_color text_normal
Definition: nuklear.h:3332
nk_panel_row_layout_type
Definition: nuklear.h:3720
struct nk_style_button contextual_button
Definition: nuklear.h:3658
Definition: nuklear.h:3059
NK_API void nk_label_wrap(struct nk_context *, const char *)
NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv)
Definition: nuklear.h:465
struct nk_style_item hover
Definition: nuklear.h:3266
NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score)
NK_API void nk_window_set_focus(struct nk_context *, const char *name)
Definition: nuklear.h:1175
Definition: nuklear.h:2030
NK_API void nk_str_delete_runes(struct nk_str *, int pos, int len)
struct nk_vec2 padding
Definition: nuklear.h:3438
#define NK_POINTER_TYPE
Definition: nuklear.h:389
Definition: nuklear.h:663
::std::string string
Definition: gtest-port.h:872
unsigned int seq
Definition: nuklear.h:3838
NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva)
#define SEEK_END
Definition: zconf.h:390
NK_API int nk_utf_encode(nk_rune, char *, int)
NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color)
nk_byte r
Definition: nuklear.h:453
float a[2]
Definition: nuklear.h:2936
Definition: nuklear.h:2719
NK_API int nk_str_append_text_char(struct nk_str *, const char *, int)
struct nk_color border_color
Definition: nuklear.h:3536
float rounding
Definition: nuklear.h:3279
NK_API void nk_fill_rect_multi_color(struct nk_command_buffer *, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom)
struct nk_memory memory
Definition: nuklear.h:2569
NK_API void nk_list_view_end(struct nk_list_view *)
struct nk_color color
Definition: nuklear.h:2965
float header_height
Definition: nuklear.h:3768
unsigned con_old
Definition: nuklear.h:3812
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3417
NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context *, struct nk_vec2)
struct nk_image img
Definition: nuklear.h:2975
nk_size begin
Definition: nuklear.h:3748
NK_API char * nk_str_at_rune(struct nk_str *, int pos, nk_rune *unicode, int *len)
struct nk_mouse_button buttons[NK_BUTTON_MAX]
Definition: nuklear.h:3049
struct nk_vec2 clicked_pos
Definition: nuklear.h:3046
Definition: nuklear.h:1722
unsigned char has_preferred_x
Definition: nuklear.h:2736
NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context *, struct nk_rect)
struct nk_window * parent
Definition: nuklear.h:3868
int index
Definition: nuklear.h:3734
Definition: nuklear.h:458
union nk_style_item_data data
Definition: nuklear.h:3255
float border
Definition: nuklear.h:3374
Definition: nuklear.h:691
NK_API nk_uint nk_color_u32(struct nk_color)
NK_API struct nk_vec2 nk_widget_position(struct nk_context *)
struct nk_color background
Definition: nuklear.h:3616
Definition: nuklear.h:463
NK_API int nk_button_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API int nk_filter_ascii(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:3694
struct nk_color bottom
Definition: nuklear.h:2895
nk_popup_type
Definition: nuklear.h:474
int prev
Definition: nuklear.h:3831
NK_API int nk_contextual_item_text(struct nk_context *, const char *, int, nk_flags align)
struct nk_page_element * next
Definition: nuklear.h:3983
nk_uint nk_flags
Definition: nuklear.h:405
float at_x
Definition: nuklear.h:3766
Definition: nuklear.h:3244
NK_API int nk_str_insert_text_char(struct nk_str *, int pos, const char *, int)
int count
Definition: nuklear.h:3709
struct nk_window * active
Definition: nuklear.h:4038
struct nk_color highlight
Definition: nuklear.h:3707
struct nk_color color
Definition: nuklear.h:3523
float rounding
Definition: nuklear.h:3578
float at_y
Definition: nuklear.h:3766
Definition: nuklear.h:2826
struct nk_style_text text
Definition: nuklear.h:3656
struct nk_vec2i b
Definition: nuklear.h:2911
nk_handle userdata
Definition: nuklear.h:3350
struct nk_color text_pressed_active
Definition: nuklear.h:3339
struct nk_color label_normal
Definition: nuklear.h:3539
Definition: nuklear.h:3588
struct nk_color combo_border_color
Definition: nuklear.h:3620
NK_API void nk_textedit_text(struct nk_text_edit *, const char *, int total_len)
NK_API void nk_str_delete_chars(struct nk_str *, int pos, int len)
struct nk_popup_buffer buf
Definition: nuklear.h:3808
Definition: nuklear.h:2835
struct nk_color color
Definition: nuklear.h:3250
nk_hash name
Definition: nuklear.h:3809
struct nk_allocator alloc
Definition: nuklear.h:3994
NK_API int nk_str_append_text_runes(struct nk_str *, const nk_rune *, int)
#define NK_INT8
Definition: nuklear.h:337
nk_command_custom_callback callback
Definition: nuklear.h:2986
Definition: nuklear.h:668
std::mutex m
Definition: faio.cpp:21
NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color)
Definition: nuklear.h:2546
NK_INT8 nk_char
Definition: nuklear.h:394
NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color)
Definition: nuklear.h:1881
struct nk_table * tables
Definition: nuklear.h:3861
struct nk_vec2 scrollbar_size
Definition: nuklear.h:3637
NK_API int nk_strtoi(const char *str, const char **endptr)
float max
Definition: nuklear.h:3708
struct nk_vec2 prev
Definition: nuklear.h:3051
enum nk_symbol_type sym_normal
Definition: nuklear.h:3550
Definition: nuklear.h:1880
Definition: nuklear.h:2721
struct nk_table * next
Definition: nuklear.h:3972
struct nk_style_item cursor_hover
Definition: nuklear.h:3403
struct nk_key keys[NK_KEY_MAX]
Definition: nuklear.h:3064
Definition: nuklear.h:3968
NK_API struct nk_style_item nk_style_item_hide(void)
NK_API int nk_combo_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
unsigned short line_thickness
Definition: nuklear.h:2951
NK_API void nk_label(struct nk_context *, const char *, nk_flags align)
nk_byte g
Definition: nuklear.h:453
Definition: nuklear.h:1715
NK_API int nk_style_set_cursor(struct nk_context *, enum nk_style_cursor)
Definition: nuklear.h:3714
int count
Definition: nuklear.h:1680
struct nk_color text_hover
Definition: nuklear.h:3273
NK_API const struct nk_command * nk__next(struct nk_context *, const struct nk_command *)
nk_tree_type
Definition: nuklear.h:476
NK_API int nk_stricmp(const char *s1, const char *s2)
Definition: nuklear.h:3487
NK_API int nk_str_insert_at_rune(struct nk_str *, int pos, const char *, int)
NK_API void nk_plot(struct nk_context *, enum nk_chart_type, const float *values, int count, int offset)
unsigned curve_segment_count
Definition: nuklear.h:987
nk_panel_type
Definition: nuklear.h:3689
short undo_point
Definition: nuklear.h:2707
int cursor
Definition: nuklear.h:2730
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3390
float delta_time_seconds
Definition: nuklear.h:4013
NK_API void nk_contextual_end(struct nk_context *)
NK_API int nk_combo_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
struct nk_command_buffer overlay
Definition: nuklear.h:4030
struct nk_command header
Definition: nuklear.h:2873
NK_API int nk_progress(struct nk_context *, nk_size *cur, nk_size max, int modifyable)
float rounding
Definition: nuklear.h:3408
short y
Definition: nuklear.h:2973
nk_size needed
Definition: nuklear.h:2541
struct nk_style_item normal
Definition: nuklear.h:3533
struct nk_vec2i begin
Definition: nuklear.h:2858
Definition: nuklear.h:1743
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3351
struct nk_buffer buffer
Definition: nuklear.h:2609
float x
Definition: nuklear.h:3756
struct nk_vec2i a
Definition: nuklear.h:2902
struct nk_style_item active
Definition: nuklear.h:3398
struct nk_style_edit edit
Definition: nuklear.h:3666
NK_API int nk_window_is_any_hovered(struct nk_context *)
Definition: nuklear.h:473
Definition: nuklear.h:3048
NK_API struct nk_vec2 nk_vec2iv(const int *xy)
unsigned short h
Definition: nuklear.h:2852
short cy
Definition: nuklear.h:2933
Definition: nuklear.h:969
unsigned char cursor_at_end_of_line
Definition: nuklear.h:2734
float border
Definition: nuklear.h:3627
NK_API int nk_combo_begin_text(struct nk_context *, const char *selected, int, struct nk_vec2 size)
#define NK_BUTTON_BEHAVIOR_STACK_SIZE
Definition: nuklear.h:3897
struct nk_style_button dec_button
Definition: nuklear.h:3384
NK_API void nk_input_glyph(struct nk_context *, const nk_glyph)
struct nk_style_item pressed_active
Definition: nuklear.h:3329
Definition: nuklear.h:475
nk_button_behavior
Definition: nuklear.h:466
NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context *, struct nk_vec2)
struct nk_vec2 label_padding
Definition: nuklear.h:3609
NK_API int nk_style_pop_float(struct nk_context *)
short y
Definition: nuklear.h:2983
float rounding
Definition: nuklear.h:3505
NK_API struct nk_rect nk_layout_space_bounds(struct nk_context *)
struct nk_table * prev
Definition: nuklear.h:3972
NK_API int nk_button_image_text_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, int, nk_flags alignment)
NK_API int nk_init_custom(struct nk_context *, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *)
struct nk_vec2i points[1]
Definition: nuklear.h:2953
Definition: nuklear.h:661
struct nk_style_tab tab
Definition: nuklear.h:3670
struct nk_color border_color
Definition: nuklear.h:3295
NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect *, struct nk_context *, struct nk_vec2)
NK_API double nk_strtod(const char *str, const char **endptr)
struct nk_window win
Definition: nuklear.h:3978
NK_API void nk_window_close(struct nk_context *ctx, const char *name)
struct nk_clipboard clip
Definition: nuklear.h:2725
nk_style_cursor
Definition: nuklear.h:2047
struct nk_window * begin
Definition: nuklear.h:4036
NK_API void nk_style_default(struct nk_context *)
NK_API void nk_input_scroll(struct nk_context *, struct nk_vec2 val)
NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect, int down)
#define NK_FLOAT_STACK_SIZE
Definition: nuklear.h:3909
Definition: nuklear.h:1719
struct nk_style_item cursor_hover
Definition: nuklear.h:3429
Definition: nuklear.h:3394
Definition: nuklear.h:2837
Definition: nuklear.h:3699
float y
Definition: nuklear.h:3716
Definition: nuklear.h:3700
int active
Definition: nuklear.h:3831
Definition: nuklear.h:665
NK_API void nk_free(struct nk_context *)
struct nk_color text_normal
Definition: nuklear.h:3468
unsigned short point_count
Definition: nuklear.h:2967
Definition: nuklear.h:496
int buffer_size
Definition: versiongenerate.py:65
Definition: nuklear.h:971
NK_API char * nk_str_at_char(struct nk_str *, int pos)
Definition: nuklear.h:699
Definition: nuklear.h:697
NK_API int nk_button_label_styled(struct nk_context *, const struct nk_style_button *, const char *title)
NK_API struct nk_color nk_rgb(int r, int g, int b)
NK_API int nk_tree_push_hashed(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
Definition: nuklear.h:474
enum nk_symbol_type sym_active
Definition: nuklear.h:3552
Definition: nuklear.h:500
NK_API void nk_combobox_separator(struct nk_context *, const char *items_separated_by_separator, int separator, int *selected, int count, int item_height, struct nk_vec2 size)
unsigned int has_scrolling
Definition: nuklear.h:3770
int len
Definition: nuklear.h:2610
unsigned int type
Definition: nuklear.h:2538
NK_API void nk_tree_state_pop(struct nk_context *)
NK_API int nk_combo_begin_label(struct nk_context *, const char *selected, struct nk_vec2 size)
NK_API int nk_stricmpn(const char *s1, const char *s2, int n)
Definition: nuklear.h:672
#define NK_UINT32
Definition: nuklear.h:359
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3449
Definition: nuklear.h:3805
NK_API int nk_style_push_flags(struct nk_context *, nk_flags *, nk_flags)
int select_start
Definition: nuklear.h:3835
int index
Definition: nuklear.h:3711
struct nk_style_item active
Definition: nuklear.h:3535
NK_API void nk_window_collapse_if(struct nk_context *, const char *name, enum nk_collapse_states, int cond)
Definition: nuklear.h:1888
struct nk_vec2 button_padding
Definition: nuklear.h:3558
Definition: nuklear.h:1741
float contextual_border
Definition: nuklear.h:3629
Definition: nuklear.h:2039
Definition: nuklear.h:1181
char text[NK_INPUT_MAX]
Definition: nuklear.h:3065
nk_uint y
Definition: nuklear.h:463
void(* nk_plugin_copy)(nk_handle, const char *, int len)
Definition: nuklear.h:482
unsigned char active
Definition: nuklear.h:2738
float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]
Definition: nuklear.h:3744
NK_API void nk_buffer_push(struct nk_buffer *, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align)
NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx)
NK_API void nk_color_fv(float *rgba_out, struct nk_color)
int state
Definition: nuklear.h:3840
NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input *, struct nk_rect)
Definition: nuklear.h:2715
Definition: nuklear.h:3453
nk_keys
Definition: nuklear.h:660
unsigned arc_segment_count
Definition: nuklear.h:986
#define NK_INT16
Definition: nuklear.h:343
struct nk_command header
Definition: nuklear.h:2972
Definition: nuklear.h:2829
Definition: nuklear.h:3585
NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
nk_size end
Definition: nuklear.h:3011
nk_style_item_type
Definition: nuklear.h:3243
const struct nk_cursor * cursor_active
Definition: nuklear.h:3652
Definition: nuklear.h:2556
unsigned circle_segment_count
Definition: nuklear.h:985
enum nk_symbol_type dec_symbol
Definition: nuklear.h:3386
int prev
Definition: nuklear.h:3821
struct nk_command header
Definition: nuklear.h:2900
Definition: nuklear.h:2608
struct nk_command header
Definition: nuklear.h:2850
Definition: nuklear.h:2033
Definition: nuklear.h:1882
struct nk_color label_hover
Definition: nuklear.h:3603
enum nk_symbol_type maximize_symbol
Definition: nuklear.h:3599
Definition: nuklear.h:467
Definition: nuklear.h:3793
struct nk_vec2i b
Definition: nuklear.h:2903
struct nk_style_button button
Definition: nuklear.h:3657
Definition: nuklear.h:1177
struct nk_style_scrollbar scrollh
Definition: nuklear.h:3668
Definition: nuklear.h:1718
NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
NK_API void nk_group_scrolled_end(struct nk_context *)
nk_handle userdata
Definition: nuklear.h:3448
unsigned active_con
Definition: nuklear.h:3813
const float * ratio
Definition: nuklear.h:3737
NK_API int nk_contextual_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
unsigned char single_line
Definition: nuklear.h:2737
Definition: nuklear.h:1892
Definition: nuklear.h:1178
struct nk_color foreground
Definition: nuklear.h:2993
struct nk_vec2 padding
Definition: nuklear.h:3640
Definition: nuklear.h:3755
Definition: nuklear.h:2025
struct nk_table tbl
Definition: nuklear.h:3976
struct nk_panel * parent
Definition: nuklear.h:3776
struct nk_style_item normal
Definition: nuklear.h:3489
struct nk_vec2 scrollbar
Definition: nuklear.h:2728
NK_API struct nk_vec2 nk_vec2(float x, float y)
unsigned char padding1
Definition: nuklear.h:2739
NK_API void nk_menubar_end(struct nk_context *)
struct nk_vec2 scrollbar_size
Definition: nuklear.h:3482
struct nk_color border_color
Definition: nuklear.h:3268
NK_API void nk_buffer_mark(struct nk_buffer *, enum nk_buffer_allocation_type type)
#define NK_WINDOW_MAX_NAME
Definition: nuklear.h:3783
Definition: nuklear.h:676
nk_uint * offset_x
Definition: nuklear.h:3764
int begin
Definition: nuklear.h:1680
typedef void(ENET_CALLBACK *ENetPacketFreeCallback)(struct _ENetPacket *)
struct nk_config_stack_user_font fonts
Definition: nuklear.h:3958
union nk_page_data data
Definition: nuklear.h:3982
Definition: nuklear.h:1885
NK_API int nk_combo_begin_symbol(struct nk_context *, enum nk_symbol_type, struct nk_vec2 size)
NK_API void nk_image(struct nk_context *, struct nk_image)
float footer_height
Definition: nuklear.h:3767
Definition: nuklear.h:2036
#define NK_VECTOR_STACK_SIZE
Definition: nuklear.h:3913
Definition: nuklear.h:2841
Definition: nuklear.h:3003
struct nk_draw_null_texture null
Definition: nuklear.h:988
NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
Definition: nuklear.h:3248
NK_API int nk_strlen(const char *str)
struct nk_style_item normal
Definition: nuklear.h:3455
float height
Definition: nuklear.h:2364
unsigned short rounding
Definition: nuklear.h:2883
Definition: nuklear.h:692
struct nk_page * next
Definition: nuklear.h:3989
NK_API float nk_strtof(const char *str, const char **endptr)
NK_UINT32 nk_uint
Definition: nuklear.h:400
struct nk_vec2 spacing
Definition: nuklear.h:3559
#define NK_SIZE_TYPE
Definition: nuklear.h:374
struct nk_color bar_active
Definition: nuklear.h:3365
Definition: nuklear.h:2822
Definition: nuklear.h:3613
struct nk_color cursor_text_normal
Definition: nuklear.h:3464
NK_API struct nk_color nk_rgb_fv(const float *rgb)
NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name)
int tree_depth
Definition: nuklear.h:3743
NK_API void nk_layout_row_template_begin(struct nk_context *, float height)
NK_API void nk_draw_text(struct nk_command_buffer *, struct nk_rect, const char *text, int len, const struct nk_user_font *, struct nk_color, struct nk_color)
float b
Definition: nuklear.h:454
enum nk_allocation_type type
Definition: nuklear.h:3995
struct nk_command header
Definition: nuklear.h:2964
unsigned int seq
Definition: nuklear.h:3844
struct nk_buffer memory
Definition: nuklear.h:4008
nk_text_align
Definition: nuklear.h:1740
NK_API struct nk_color nk_hsva_iv(const int *hsva)
NK_API void nk_combobox(struct nk_context *, const char **items, int count, int *selected, int item_height, struct nk_vec2 size)
struct nk_scroll scrollbar
Definition: nuklear.h:3825
NK_API void nk_buffer_reset(struct nk_buffer *, enum nk_buffer_allocation_type type)
NK_API int nk_str_insert_text_runes(struct nk_str *, int pos, const nk_rune *, int)
enum nk_symbol_type sym_maximize
Definition: nuklear.h:3574
NK_API void nk_textedit_delete_selection(struct nk_text_edit *)
int active
Definition: nuklear.h:3752
struct nk_window * end
Definition: nuklear.h:4037
Definition: nuklear.h:680
Definition: nuklear.h:2031
struct nk_rect item
Definition: nuklear.h:3742
NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color)
NK_API int nk_group_scrolled_offset_begin(struct nk_context *, nk_uint *x_offset, nk_uint *y_offset, const char *, nk_flags)
float item_offset
Definition: nuklear.h:3740
Definition: nuklear.h:461
struct nk_color text
Definition: nuklear.h:3566
NK_API struct nk_color nk_rgba(int r, int g, int b, int a)
Definition: nuklear.h:2553
NK_API void * nk_buffer_memory(struct nk_buffer *)
nk_text_edit_type
Definition: nuklear.h:2713
NK_API void nk_textedit_init_fixed(struct nk_text_edit *, void *memory, nk_size size)
NK_API int nk_init_fixed(struct nk_context *, void *memory, nk_size size, const struct nk_user_font *)
unsigned short h
Definition: nuklear.h:2885
#define NK_SATURATE(x)
Definition: nuklear.h:4053
struct nk_style_slider slider
Definition: nuklear.h:3663
struct nk_color label_active
Definition: nuklear.h:3497
Definition: nuklear.h:2022
Definition: nuklear.h:3728
NK_API void nk_stroke_curve(struct nk_command_buffer *, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color)
float popup_border
Definition: nuklear.h:3633
NK_API int nk_button_image(struct nk_context *, struct nk_image img)
NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region)
nk_hash name
Definition: nuklear.h:3818
float border
Definition: nuklear.h:3555
nk_size parent
Definition: nuklear.h:3749
NK_API int nk_combo(struct nk_context *, const char **items, int count, int selected, int item_height, struct nk_vec2 size)
Definition: nuklear.h:3843
Definition: nuklear.h:2043
Definition: nuklear.h:1182
nk_byte a
Definition: nuklear.h:453
NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a)
NK_API void nk_str_clear(struct nk_str *)
float rounding
Definition: nuklear.h:3527
float a[2]
Definition: nuklear.h:2944
#define NK_TEXTEDIT_UNDOCHARCOUNT
Definition: nuklear.h:2687
NK_API const void * nk_buffer_memory_const(const struct nk_buffer *)
#define nk_ptr_add_const(t, p, i)
Definition: nuklear.h:4070
Definition: nuklear.h:2836
NK_API void nk_buffer_init_fixed(struct nk_buffer *, void *memory, nk_size size)
float x
Definition: nuklear.h:457
Definition: nuklear.h:977
Definition: nuklear.h:2020
NK_API void nk_popup_close(struct nk_context *)
NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color)
Definition: nuklear.h:2032
enum nk_symbol_type inc_symbol
Definition: nuklear.h:3444
short x
Definition: nuklear.h:2994
nk_uint nk_rune
Definition: nuklear.h:406
struct nk_color text_active
Definition: nuklear.h:3274
struct nk_page_element * freelist
Definition: nuklear.h:3998
struct nk_window * next
Definition: nuklear.h:3866
NK_API struct nk_color nk_color_picker(struct nk_context *, struct nk_color, enum nk_color_format)
struct nk_vec2 combo_padding
Definition: nuklear.h:3643
NK_API int nk_str_append_text_utf8(struct nk_str *, const char *, int)
struct nk_color text_hover
Definition: nuklear.h:3303
NK_API void nk_text_colored(struct nk_context *, const char *, int, nk_flags, struct nk_color)
int end
Definition: nuklear.h:1680
struct nk_config_stack_flags flags
Definition: nuklear.h:3956
nk_panel_set
Definition: nuklear.h:3698
unsigned short w
Definition: nuklear.h:2995
float x
Definition: nuklear.h:3716
struct nk_image image
Definition: nuklear.h:3249
float cursor_rounding
Definition: nuklear.h:3411
NK_API int nk_checkbox_flags_text(struct nk_context *, const char *, int, unsigned int *flags, unsigned int value)
Definition: nuklear.h:3975
NK_API int nk_button_image_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img)
unsigned short line_thickness
Definition: nuklear.h:2865
int total_height
Definition: nuklear.h:1682
NK_API struct nk_rect nk_rect(float x, float y, float w, float h)
struct nk_vec2 touch_padding
Definition: nuklear.h:3282
Definition: nuklear.h:3797
nk_orientation
Definition: nuklear.h:468
NK_API void nk_style_show_cursor(struct nk_context *)
struct nk_color text_background
Definition: nuklear.h:3340
struct nk_window * prev
Definition: nuklear.h:3867
int cursor
Definition: nuklear.h:3822
struct nk_vec2 min_size
Definition: nuklear.h:3638
struct nk_command header
Definition: nuklear.h:2932
struct nk_color color
Definition: nuklear.h:2928
float spacing
Definition: nuklear.h:3311
struct nk_style_item normal
Definition: nuklear.h:3590
Definition: nuklear.h:2823
struct nk_vec2 padding
Definition: nuklear.h:3608
nk_widget_layout_states
Definition: nuklear.h:1709
Definition: nuklear.h:2830
struct nk_style_scrollbar scrollv
Definition: nuklear.h:3669
NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value)
Definition: nuklear.h:3420
enum nk_anti_aliasing line_AA
Definition: nuklear.h:983
struct nk_style_item active
Definition: nuklear.h:3267
nk_collapse_states
Definition: nuklear.h:469
short redo_point
Definition: nuklear.h:2708
NK_API const char * nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len)
Definition: nuklear.h:499
Definition: nuklear.h:456
NK_API int nk_chart_begin_colored(struct nk_context *, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max)
NK_API void nk_style_hide_cursor(struct nk_context *)
NK_API int nk_menu_begin_image_text(struct nk_context *, const char *, int, nk_flags align, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:3724
struct nk_color border_color
Definition: nuklear.h:3360
Definition: nuklear.h:1712
Definition: nuklear.h:2024
NK_API int nk_group_scrolled_begin(struct nk_context *, struct nk_scroll *, const char *title, nk_flags)
struct nk_color color
Definition: nuklear.h:2886
NK_API void nk_str_remove_runes(struct nk_str *str, int len)
struct nk_vec2 spacing
Definition: nuklear.h:3636
float item_width
Definition: nuklear.h:3738
Definition: nuklear.h:2825
Definition: nuklear.h:2049
Definition: nuklear.h:3355
#define NK_ALIGN_PTR(x, mask)
Definition: nuklear.h:4091
struct nk_color color
Definition: nuklear.h:2905
int cursor_visible
Definition: nuklear.h:3654
NK_API int nk_widget_has_mouse_click_down(struct nk_context *, enum nk_buttons, int down)
#define NK_CLAMP(i, v, x)
Definition: nuklear.h:317
struct nk_style_combo combo
Definition: nuklear.h:3671
struct nk_style_property property
Definition: nuklear.h:3665
unsigned short region[4]
Definition: nuklear.h:461
NK_API void nk_input_begin(struct nk_context *)
int length
Definition: nuklear.h:3833
struct nk_window * win
Definition: nuklear.h:3806
struct nk_color contextual_border_color
Definition: nuklear.h:3621
Definition: nuklear.h:2908
NK_API int nk_option_text(struct nk_context *, const char *, int, int active)
void * ptr
Definition: nuklear.h:460
struct nk_menu_state menu
Definition: nuklear.h:3772
NK_API void nk_stroke_rect(struct nk_command_buffer *, struct nk_rect, float rounding, float line_thickness, struct nk_color)
NK_API int nk_menu_begin_symbol_text(struct nk_context *, const char *, int, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
NK_API void nk_push_scissor(struct nk_command_buffer *, struct nk_rect)
NK_API const struct nk_command * nk__begin(struct nk_context *)
NK_API nk_flags nk_chart_push_slot(struct nk_context *, float, int)
Definition: nuklear.h:2027
nk_edit_flags
Definition: nuklear.h:1876
#define NK_INBOX(px, py, x, y, w, h)
Definition: nuklear.h:4057
int value
Definition: der_length_ia5_string.c:21
#define nk_vec2_sub(a, b)
Definition: nuklear.h:4064
Definition: nuklear.h:470
NK_API int nk_str_append_str_char(struct nk_str *, const char *)
float indent
Definition: nuklear.h:3579
Definition: nuklear.h:700
struct nk_color selected_color
Definition: nuklear.h:3522
unsigned char initialized
Definition: nuklear.h:2735
Definition: nuklear.h:2028
Definition: nuklear.h:1180
NK_API int nk_input_is_key_down(const struct nk_input *, enum nk_keys)
Definition: nuklear.h:501
NK_API int nk_window_is_hovered(struct nk_context *)
short x
Definition: nuklear.h:2973
NK_API double nk_propertyd(struct nk_context *, const char *name, double min, double val, double max, double step, float inc_per_pixel)
#define NK_PI
Definition: nuklear.h:4048
struct nk_cursor * cursor_last
Definition: nuklear.h:3653
nk_size last
Definition: nuklear.h:3011
NK_API int nk_filter_decimal(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:1898
Definition: nuklear.h:469
float height
Definition: nuklear.h:2996
NK_API int nk_filter_binary(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_init(struct nk_context *, struct nk_allocator *, const struct nk_user_font *)
Definition: nuklear.h:2029
NK_API int nk_radio_label(struct nk_context *, const char *, int *active)
struct nk_vec2 spacing
Definition: nuklear.h:3610
NK_API void nk_contextual_close(struct nk_context *)
short y
Definition: nuklear.h:2918
NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
void(* nk_command_custom_callback)(void *canvas, short x, short y, unsigned short w, unsigned short h, nk_handle callback_data)
Definition: nuklear.h:2979
NK_API void nk_textedit_init(struct nk_text_edit *, struct nk_allocator *, nk_size size)
const struct nk_cursor * cursors[NK_CURSOR_COUNT]
Definition: nuklear.h:3651
struct nk_vec2 spacing
Definition: nuklear.h:3378
const struct nk_draw_vertex_layout_element * vertex_layout
Definition: nuklear.h:989
struct nk_style_chart chart
Definition: nuklear.h:3667
#define NK_UTF_SIZE
Definition: nuklear.h:255
struct nk_vec2 popup_padding
Definition: nuklear.h:3642
NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols)
short delete_length
Definition: nuklear.h:2700
NK_API void nk_fill_arc(struct nk_command_buffer *, float cx, float cy, float radius, float a_min, float a_max, struct nk_color)
NK_API const char * nk_str_get_const(const struct nk_str *)
NK_API int nk_textedit_cut(struct nk_text_edit *)
Definition: nuklear.h:972
NK_API void nk_property_double(struct nk_context *, const char *name, double min, double *val, double max, double step, float inc_per_pixel)
Definition: nuklear.h:3562
struct nk_color cursor_text_hover
Definition: nuklear.h:3465
NK_API int nk_button_image_label_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, nk_flags text_alignment)
NK_API int nk_combo_separator(struct nk_context *, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size)
NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color)
float border
Definition: nuklear.h:3434
float rounding
Definition: nuklear.h:3375
NK_API void nk_stroke_polyline(struct nk_command_buffer *, float *points, int point_count, float line_thickness, struct nk_color col)
NK_API void nk_text_wrap_colored(struct nk_context *, const char *, int, struct nk_color)
NK_API enum nk_widget_layout_states nk_widget(struct nk_rect *, const struct nk_context *)
nk_edit_events
Definition: nuklear.h:1897
NK_API struct nk_vec2 nk_rect_pos(struct nk_rect)
Definition: nuklear.h:3723
struct nk_text_undo_state undo
Definition: nuklear.h:2741
NK_API int nk_input_is_mouse_released(const struct nk_input *, enum nk_buttons)
Definition: nuklear.h:2037
NK_API void nk_property_int(struct nk_context *, const char *name, int min, int *val, int max, int step, float inc_per_pixel)
struct nk_style_button button
Definition: nuklear.h:3549
#define NK_SCROLLBAR_HIDING_TIMEOUT
Definition: nuklear.h:263
enum nk_symbol_type sym_right
Definition: nuklear.h:3501
Definition: nuklear.h:3649
NK_API void nk_color_hex_rgba(char *output, struct nk_color)
#define NK_MIN(a, b)
Definition: nuklear.h:315
Definition: nuklear.h:3791
struct nk_vec2 group_padding
Definition: nuklear.h:3641
Definition: nuklear.h:468
nk_handle userdata
Definition: nuklear.h:485
NK_API void nk_style_load_cursor(struct nk_context *, enum nk_style_cursor, const struct nk_cursor *)
unsigned int size
Definition: nuklear.h:3988
Definition: nuklear.h:455
Definition: nuklear.h:457
NK_API int nk_input_is_mouse_pressed(const struct nk_input *, enum nk_buttons)
Definition: nuklear.h:2038
struct nk_style_item cursor_normal
Definition: nuklear.h:3369
#define NK_VALUE_PAGE_CAPACITY
Definition: nuklear.h:3965
Definition: nuklear.h:474
NK_API void nk_push_custom(struct nk_command_buffer *, struct nk_rect, nk_command_custom_callback, nk_handle usr)
Definition: nuklear.h:2956
Definition: nuklear.h:490
enum nk_style_header_align align
Definition: nuklear.h:3607
NK_API int nk_str_len_char(struct nk_str *)
int active
Definition: nuklear.h:2557
Definition: nuklear.h:2052
unsigned int clicked
Definition: nuklear.h:3061
NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input *, struct nk_rect)
void * ptr
Definition: nuklear.h:2561
Definition: nuklear.h:2023
NK_API const char * nk_style_get_color_by_name(enum nk_style_colors)
void(* nk_query_font_glyph_f)(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
Definition: nuklear.h:2344
Definition: nuklear.h:3727
NK_API void nk_stroke_arc(struct nk_command_buffer *, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color)
Definition: nuklear.h:975
Definition: nuklear.h:2704
Definition: nuklear.h:662
nk_size vertex_alignment
Definition: nuklear.h:991
NK_API void nk_tooltip_end(struct nk_context *)
Definition: nuklear.h:679
Definition: nuklear.h:502
struct nk_color border_color
Definition: nuklear.h:3521
struct nk_style_item cursor_normal
Definition: nuklear.h:3402
unsigned short h
Definition: nuklear.h:2920
Definition: nuklear.h:1900
Definition: nuklear.h:503
short w
Definition: nuklear.h:458
NK_API void nk_spacing(struct nk_context *, int cols)
Definition: nuklear.h:467
Definition: nuklear.h:2536
Definition: nuklear.h:682
struct nk_color text_background
Definition: nuklear.h:3271
float y
Definition: nuklear.h:455
NK_API struct nk_color nk_rgba_hex(const char *rgb)
struct nk_vec2i points[1]
Definition: nuklear.h:2960
struct nk_vec2 padding
Definition: nuklear.h:3580
struct nk_command header
Definition: nuklear.h:2957
struct nk_style_item active
Definition: nuklear.h:3491
GLuint texture
Definition: sdl2backend.cpp:518
NK_API int nk_button_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags text_alignment)
#define NK_STATIC_ASSERT(exp)
Definition: nuklear.h:304
NK_API struct nk_image nk_subimage_ptr(void *, unsigned short w, unsigned short h, struct nk_rect sub_region)
NK_API void nk_text_wrap(struct nk_context *, const char *, int)
NK_API struct nk_image nk_image_handle(nk_handle)
NK_API struct nk_image nk_image_ptr(void *)
short y
Definition: nuklear.h:2926
NK_API float nk_window_get_width(const struct nk_context *)
NK_API int nk_image_is_subimage(const struct nk_image *img)
nk_size begin
Definition: nuklear.h:3011
struct nk_command header
Definition: nuklear.h:2882
Definition: nuklear.h:973
Definition: nuklear.h:1179
NK_API int nk_style_push_font(struct nk_context *, struct nk_user_font *)
struct nk_context * ctx
Definition: nuklear.h:1683
unsigned char mode
Definition: nuklear.h:2733
struct nk_style_item hover
Definition: nuklear.h:3358
unsigned short h
Definition: nuklear.h:2995
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
struct nk_color text_hover_active
Definition: nuklear.h:3338
NK_API int nk_selectable_label(struct nk_context *, const char *, nk_flags align, int *value)
struct nk_style_button tab_minimize_button
Definition: nuklear.h:3570
struct nk_vec2 padding
Definition: nuklear.h:3483
NK_API struct nk_color nk_hsva(int h, int s, int v, int a)
struct nk_vec2 spacing
Definition: nuklear.h:3581
#define NK_STYLE_ITEM_STACK_SIZE
Definition: nuklear.h:3905
Definition: nuklear.h:669
NK_API int nk_str_insert_text_utf8(struct nk_str *, int pos, const char *, int)
Definition: nuklear.h:3263
NK_API void nk_tooltip(struct nk_context *, const char *)
Definition: nuklear.h:2562
struct nk_color text_active
Definition: nuklear.h:3304
#define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
Definition: nuklear.h:3683
nk_plugin_alloc alloc
Definition: nuklear.h:486
NK_API void nk_combo_close(struct nk_context *)
struct nk_color text_hover
Definition: nuklear.h:3469
NK_API int nk_radio_text(struct nk_context *, const char *, int, int *active)
NK_API void nk_buffer_clear(struct nk_buffer *)
Definition: nuklear.h:3760
nk_uint scroll_value
Definition: nuklear.h:1685
short undo_char_point
Definition: nuklear.h:2709
enum nk_symbol_type sym_hover
Definition: nuklear.h:3551
enum nk_symbol_type close_symbol
Definition: nuklear.h:3597
int id
Definition: nuklear.h:460
Definition: nuklear.h:2361
NK_API struct nk_vec2 nk_window_get_size(const struct nk_context *)
Definition: nuklear.h:465
nk_uint * offset_y
Definition: nuklear.h:3765
struct nk_command header
Definition: nuklear.h:2949
struct nk_color label_hover
Definition: nuklear.h:3496
Definition: nuklear.h:1717
nk_size end
Definition: nuklear.h:3751
int select_end
Definition: nuklear.h:2732
NK_API const char * nk_str_at_char_const(const struct nk_str *, int pos)
struct nk_configuration_stacks stacks
Definition: nuklear.h:4012
struct nk_style_item cursor_active
Definition: nuklear.h:3430
Definition: nuklear.h:1899
Definition: nuklear.h:2899
NK_API nk_handle nk_handle_id(int)
NK_API int nk_combo_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
unsigned short h
Definition: nuklear.h:2892
NK_UINT8 nk_uchar
Definition: nuklear.h:395
int active
Definition: nuklear.h:3821
NK_API struct nk_color nk_rgb_f(float r, float g, float b)
Definition: nuklear.h:2720
enum nk_allocation_type type
Definition: nuklear.h:2567
float r
Definition: nuklear.h:454
nk_window_flags
Definition: nuklear.h:3787
short x
Definition: nuklear.h:2891
nk_chart_type
Definition: nuklear.h:471
float x
Definition: nuklear.h:455
struct nk_color symbol_hover
Definition: nuklear.h:3545
struct nk_mouse mouse
Definition: nuklear.h:3071
enum nk_chart_type type
Definition: nuklear.h:3705
Definition: nuklear.h:498
struct nk_rect bounds
Definition: nuklear.h:3763
Definition: nuklear.h:2017
Definition: nuklear.h:2547
NK_API int nk_contextual_item_label(struct nk_context *, const char *, nk_flags align)
#define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)
Definition: nuklear.h:3924
struct nk_color border_color
Definition: nuklear.h:3425
NK_API int nk_list_view_begin(struct nk_context *, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count)
float rounding
Definition: nuklear.h:3480
nk_size size
Definition: nuklear.h:4000
struct nk_vec2 padding
Definition: nuklear.h:3345
NK_API void nk_stroke_polygon(struct nk_command_buffer *, float *, int point_count, float line_thickness, struct nk_color)
unsigned combo_count
Definition: nuklear.h:3811
NK_API void nk_popup_end(struct nk_context *)
int build
Definition: nuklear.h:4033
struct nk_page * pages
Definition: nuklear.h:3997
NK_API void nk_input_motion(struct nk_context *, int x, int y)
NK_API int nk_textedit_paste(struct nk_text_edit *, char const *, int len)
Definition: nuklear.h:3320
NK_API int nk_color_pick(struct nk_context *, struct nk_color *, enum nk_color_format)
Definition: nuklear.h:2828
NK_API int nk_utf_len(const char *, int byte_len)
float g
Definition: nuklear.h:454
Definition: nuklear.h:974
NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading)
Definition: nuklear.h:1716
nk_size vertex_size
Definition: nuklear.h:990
unsigned short w
Definition: nuklear.h:2920
Definition: nuklear.h:1720
NK_API struct nk_color nk_hsva_fv(const float *hsva)
Definition: nuklear.h:462
Definition: nuklear.h:696
nk_size cap
Definition: nuklear.h:4001
Definition: nuklear.h:1883
Definition: nuklear.h:1176
enum nk_symbol_type inc_symbol
Definition: nuklear.h:3385
NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color)
Definition: nuklear.h:3987
struct nk_keyboard keyboard
Definition: nuklear.h:3070
unsigned short rounding
Definition: nuklear.h:2874
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3352
#define NK_UINT16
Definition: nuklear.h:346
Definition: nuklear.h:475
unsigned short w
Definition: nuklear.h:461
Definition: nuklear.h:2924
unsigned short w
Definition: nuklear.h:2927
#define NK_TEXTEDIT_UNDOSTATECOUNT
Definition: nuklear.h:2683
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3515
NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value)
struct nk_style_scrollbar scrollbar
Definition: nuklear.h:3459
struct nk_color bar_normal
Definition: nuklear.h:3363
nk_flags last_widget_state
Definition: nuklear.h:4010
Definition: nuklear.h:3801
#define nk_foreach(c, ctx)
Definition: nuklear.h:1011
struct nk_color color
Definition: nuklear.h:3706
struct nk_command header
Definition: nuklear.h:2925
int(* nk_plugin_filter)(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:480
struct nk_style_item normal_active
Definition: nuklear.h:3327
Definition: nuklear.h:476
NK_API float nk_window_get_height(const struct nk_context *)
NK_API float nk_widget_height(struct nk_context *)
NK_API int nk_menu_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
NK_API int nk_slide_int(struct nk_context *, int min, int val, int max, int step)
Definition: nuklear.h:3732
NK_API int nk_filter_oct(const struct nk_text_edit *, nk_rune unicode)
float filled
Definition: nuklear.h:3741
#define NK_LEN(a)
Definition: nuklear.h:4054
NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
Definition: nuklear.h:2827
Definition: nuklear.h:2989
Definition: nuklear.h:693
NK_API int nk_slider_float(struct nk_context *, float min, float *val, float max, float step)
NK_API int nk_window_is_hidden(struct nk_context *, const char *)
NK_API void nk_fill_triangle(struct nk_command_buffer *, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color)
Definition: nuklear.h:1879
short cx
Definition: nuklear.h:2933
#define NK_INTERN
Definition: nuklear.h:286
struct nk_command_buffer buffer
Definition: nuklear.h:3851
NK_API int nk_slider_int(struct nk_context *, int min, int *val, int max, int step)
nk_size allocated
Definition: nuklear.h:2540
nk_hash name
Definition: nuklear.h:3837
Definition: nuklear.h:468
struct nk_vec2i end
Definition: nuklear.h:2859
NK_API int nk_contextual_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
unsigned con_count
Definition: nuklear.h:3812
NK_API void nk_input_button(struct nk_context *, enum nk_buttons, int x, int y, int down)
NK_API int nk_item_is_any_active(struct nk_context *)
NK_API void nk_label_colored_wrap(struct nk_context *, const char *, struct nk_color)
struct nk_style_toggle checkbox
Definition: nuklear.h:3661
void(* draw_end)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:3287
NK_API void nk_input_key(struct nk_context *, enum nk_keys, int down)
NK_API struct nk_style_item nk_style_item_color(struct nk_color)
Definition: nuklear.h:2849
#define SEEK_SET
Definition: zconf.h:388
Definition: nuklear.h:677
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
NK_API int nk_button_push_behavior(struct nk_context *, enum nk_button_behavior)
unsigned short table_count
Definition: nuklear.h:3862
#define nk_ptr_add(t, p, i)
Definition: nuklear.h:4069
NK_API float nk_slide_float(struct nk_context *, float min, float val, float max, float step)
NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color)
Definition: nuklear.h:667
NK_API void nk_fill_polygon(struct nk_command_buffer *, float *, int point_count, struct nk_color)
nk_size size
Definition: nuklear.h:2561
short x
Definition: nuklear.h:2876
NK_API float nk_widget_width(struct nk_context *)
struct nk_color border_color
Definition: nuklear.h:3399
Definition: nuklear.h:1746
Definition: nuklear.h:3531
#define nk_vec2_add(a, b)
Definition: nuklear.h:4065
NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input *, struct nk_rect)
float cursor_border
Definition: nuklear.h:3410
NK_API int nk_chart_begin(struct nk_context *, enum nk_chart_type, int num, float min, float max)
NK_API int nk_style_pop_vec2(struct nk_context *)
Definition: nuklear.h:2053
struct nk_config_stack_style_item style_items
Definition: nuklear.h:3953
NK_API nk_size nk_buffer_total(struct nk_buffer *)
nk_size size
Definition: nuklear.h:2539
Definition: nuklear.h:681
NK_API nk_handle nk_handle_ptr(void *)
unsigned short h
Definition: nuklear.h:2984
unsigned int clicked
Definition: nuklear.h:3045
struct nk_style_item cursor_active
Definition: nuklear.h:3371
NK_API void nk_window_show(struct nk_context *, const char *name, enum nk_show_states)
struct nk_style style
Definition: nuklear.h:4007
Definition: nuklear.h:1751
NK_API void nk_tree_pop(struct nk_context *)
float range
Definition: nuklear.h:3708
const struct nk_user_font * font
Definition: nuklear.h:2991
Definition: gtest_output_test_.cc:544
NK_API void nk_textedit_undo(struct nk_text_edit *)
NK_API unsigned nk_check_flags_text(struct nk_context *, const char *, int, unsigned int flags, unsigned int value)
unsigned int count
Definition: nuklear.h:4041
struct nk_popup_state popup
Definition: nuklear.h:3857
NK_API float nk_layout_ratio_from_pixel(struct nk_context *, float pixel_width)
Definition: nuklear.h:1749
struct nk_vec2 padding
Definition: nuklear.h:3280
NK_API nk_flags nk_edit_buffer(struct nk_context *, nk_flags, struct nk_text_edit *, nk_plugin_filter)
float y
Definition: nuklear.h:457
int active
Definition: nuklear.h:3810
short x
Definition: nuklear.h:456
struct nk_color right
Definition: nuklear.h:2896
Definition: nuklear.h:3695
NK_API int nk_style_pop_style_item(struct nk_context *)
nk_handle userdata
Definition: nuklear.h:2362
Definition: nuklear.h:497
uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len)
Definition: adler32.c:60
struct nk_style_item hover
Definition: nuklear.h:3423
nk_plugin_filter filter
Definition: nuklear.h:2727
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3416
struct nk_style_item normal
Definition: nuklear.h:3422
NK_API int nk_checkbox_flags_label(struct nk_context *, const char *, unsigned int *flags, unsigned int value)
struct nk_color symbol_active
Definition: nuklear.h:3546
nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]
Definition: nuklear.h:2706
float scrollbar_hiding_timer
Definition: nuklear.h:3853
NK_API int nk_str_append_str_utf8(struct nk_str *, const char *)
nk_text_alignment
Definition: nuklear.h:1748
Definition: nuklear.h:2821
#define NK_API
Definition: nuklear.h:282
struct nk_rect bounds
Definition: nuklear.h:3849
Definition: nuklear.h:2714
unsigned short w
Definition: nuklear.h:2984
NK_API int nk_window_is_active(struct nk_context *, const char *)
Definition: nuklear.h:471
unsigned short line_thickness
Definition: nuklear.h:2919
Definition: nuklear.h:466
struct nk_style_window_header header
Definition: nuklear.h:3614
Definition: nuklear.h:3586
float global_alpha
Definition: nuklear.h:982
struct nk_command header
Definition: nuklear.h:2890
Definition: nuklear.h:2981
struct nk_color color
Definition: nuklear.h:2878
Definition: nuklear.h:470
unsigned capacity
Definition: nuklear.h:3999
NK_API int nk_style_push_color(struct nk_context *, struct nk_color *, struct nk_color)
struct nk_vec2 padding
Definition: nuklear.h:3528
Definition: nuklear.h:1886
NK_API void nk_style_load_all_cursors(struct nk_context *, struct nk_cursor *)
struct nk_vec2 touch_padding
Definition: nuklear.h:3346
struct nk_color color
Definition: nuklear.h:2950
struct nk_style_item fixed_background
Definition: nuklear.h:3615
Definition: nuklear.h:2019
nk_byte b
Definition: nuklear.h:453
NK_API int nk_input_has_mouse_click(const struct nk_input *, enum nk_buttons)
NK_API int nk_combo_begin_color(struct nk_context *, struct nk_color color, struct nk_vec2 size)
NK_API void nk_str_free(struct nk_str *)
int show_buttons
Definition: nuklear.h:3382
NK_API int nk_option_label(struct nk_context *, const char *, int active)
nk_size last
Definition: nuklear.h:3750
float border
Definition: nuklear.h:3409
nk_allocation_type
Definition: nuklear.h:2545
void(* nk_plugin_free)(nk_handle, void *old)
Definition: nuklear.h:479
struct nk_vec2i a
Definition: nuklear.h:2910
nk_plugin_paste paste
Definition: nuklear.h:2693
NK_API int nk_combo_begin_image_label(struct nk_context *, const char *selected, struct nk_image, struct nk_vec2 size)
struct nk_color cursor_border_color
Definition: nuklear.h:3431
nk_size next
Definition: nuklear.h:2843
struct nk_color color
Definition: nuklear.h:2958
struct nk_style_item background
Definition: nuklear.h:3564
Definition: nuklear.h:2034
NK_API void nk_textedit_free(struct nk_text_edit *)
struct nk_scroll scrollbar
Definition: nuklear.h:3850
NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color)
struct nk_buffer * base
Definition: nuklear.h:3007
float(* nk_text_width_f)(nk_handle, float h, const char *, int len)
Definition: nuklear.h:2343
int use_clipping
Definition: nuklear.h:3009
NK_API struct nk_command_buffer * nk_window_get_canvas(struct nk_context *)
NK_API int nk_checkbox_text(struct nk_context *, const char *, int, int *active)
nk_uint nk_hash
Definition: nuklear.h:404
NK_API int nk_str_len(struct nk_str *)
nk_command_type
Definition: nuklear.h:2818
NK_API nk_flags nk_edit_string(struct nk_context *, nk_flags, char *buffer, int *len, int max, nk_plugin_filter)
NK_API void nk_edit_unfocus(struct nk_context *)
unsigned int old
Definition: nuklear.h:3820
nk_size calls
Definition: nuklear.h:2542
Definition: nuklear.h:686
Definition: nuklear.h:1745
struct nk_vec2 pos
Definition: nuklear.h:3050
Definition: nuklear.h:2551
struct nk_style_item hover
Definition: nuklear.h:3490
Definition: nuklear.h:684
NK_API int nk_combo_item_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags alignment)
NK_API int nk_combo_begin_symbol_text(struct nk_context *, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size)
Definition: nuklear.h:2045
#define NK_INPUT_MAX
Definition: nuklear.h:257
NK_API int nk_menu_begin_symbol_label(struct nk_context *, const char *, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
Definition: nuklear.h:1893
NK_API void nk_buffer_free(struct nk_buffer *)
Definition: nuklear.h:2831
struct nk_style_item hover
Definition: nuklear.h:3591
NK_API struct nk_color nk_hsv_f(float h, float s, float v)
nk_hash name
Definition: nuklear.h:3845
struct nk_style_item cursor_active
Definition: nuklear.h:3404
struct nk_color color
Definition: nuklear.h:2921
struct nk_style_item normal
Definition: nuklear.h:3357
NK_API int nk_button_symbol(struct nk_context *, enum nk_symbol_type)
NK_API int nk_checkbox_label(struct nk_context *, const char *, int *active)
int use_pool
Definition: nuklear.h:4034
enum nk_symbol_type minimize_symbol
Definition: nuklear.h:3598
struct nk_vec2 scroll_delta
Definition: nuklear.h:3053
enum nk_panel_type type
Definition: nuklear.h:3807
NK_API int nk_window_is_closed(struct nk_context *, const char *)
struct nk_vec2 padding
Definition: nuklear.h:3309
Definition: nuklear.h:469
Definition: nuklear.h:685
NK_API int nk_group_begin(struct nk_context *, const char *title, nk_flags)
struct nk_rect header
Definition: nuklear.h:3814
float h
Definition: nuklear.h:3756
Definition: nuklear.h:2971
Definition: nuklear.h:2916
NK_API void nk_buffer_info(struct nk_memory_status *, struct nk_buffer *)
NK_API const char * nk_str_at_const(const struct nk_str *, int pos, nk_rune *unicode, int *len)
struct nk_color symbol_normal
Definition: nuklear.h:3544
struct nk_vec2 delta
Definition: nuklear.h:3052
Definition: nuklear.h:3952
#define NK_COLOR_STACK_SIZE
Definition: nuklear.h:3921
float row_padding
Definition: nuklear.h:3484
int down
Definition: nuklear.h:3044
struct nk_style_item normal
Definition: nuklear.h:3292
enum nk_panel_row_layout_type type
Definition: nuklear.h:3733
NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color)
Definition: nuklear.h:981
#define NK_BETWEEN(x, a, b)
Definition: nuklear.h:4056
NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx)
NK_API void nk_clear(struct nk_context *)
struct nk_color cursor_border_color
Definition: nuklear.h:3405
Definition: nuklear.h:2021
Definition: nuklear.h:674
float w
Definition: nuklear.h:457
struct nk_color border_color
Definition: nuklear.h:3492
NK_API void nk_menu_end(struct nk_context *)
#define NK_CONTAINER_OF(ptr, type, member)
Definition: nuklear.h:4097
struct nk_style_item hover
Definition: nuklear.h:3323
NK_API int nk_selectable_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int *value)
struct nk_style_button minimize_button
Definition: nuklear.h:3596
struct nk_style_item cursor_normal
Definition: nuklear.h:3428
NK_API nk_flags nk_chart_push(struct nk_context *, float)
NK_API unsigned nk_check_flags_label(struct nk_context *, const char *, unsigned int flags, unsigned int value)
float rounding
Definition: nuklear.h:3344
NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags)
NK_API float nk_propertyf(struct nk_context *, const char *name, float min, float val, float max, float step, float inc_per_pixel)
NK_API int nk_input_is_key_released(const struct nk_input *, enum nk_keys)
Definition: nuklear.h:495
struct nk_color cursor_hover
Definition: nuklear.h:3463
struct nk_style_item hover
Definition: nuklear.h:3397
Definition: nuklear.h:2863
Definition: nuklear.h:2948
enum nk_command_type type
Definition: nuklear.h:2842
float rounding
Definition: nuklear.h:3556
struct nk_style_button inc_button
Definition: nuklear.h:3442
struct nk_color text_active
Definition: nuklear.h:3470
NK_API struct nk_rect nk_widget_bounds(struct nk_context *)
struct nk_config_stack_vec2 vectors
Definition: nuklear.h:3955
float border
Definition: nuklear.h:3577
Definition: nuklear.h:473
Definition: nuklear.h:2824
short y
Definition: nuklear.h:2851
NK_API void nk_window_show_if(struct nk_context *, const char *name, enum nk_show_states, int cond)
NK_API int nk_tree_image_push_hashed(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
nk_color_format
Definition: nuklear.h:473
struct nk_command header
Definition: nuklear.h:2990
float combo_border
Definition: nuklear.h:3628
struct nk_color cursor_normal
Definition: nuklear.h:3462
struct nk_command header
Definition: nuklear.h:2982
nk_hash keys[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:3970
NK_API struct nk_color nk_hsv_iv(const int *hsv)
NK_API int nk_menu_begin_image(struct nk_context *, const char *, struct nk_image, struct nk_vec2 size)
struct nk_color popup_border_color
Definition: nuklear.h:3619
NK_API int nk_menu_begin_image_label(struct nk_context *, const char *, nk_flags align, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:3981
NK_API int nk_str_insert_at_char(struct nk_str *, int pos, const char *, int)
Definition: nuklear.h:1711
Definition: nuklear.h:2691
NK_API int nk_selectable_text(struct nk_context *, const char *, int, nk_flags align, int *value)
NK_UINT16 nk_ushort
Definition: nuklear.h:398
Definition: nuklear.h:2963
Definition: nuklear.h:1742
Definition: nuklear.h:3795
unsigned int old
Definition: nuklear.h:3839
nk_size size
Definition: nuklear.h:2579
enum nk_panel_type type
Definition: nuklear.h:3761
NK_API int nk_input_is_mouse_down(const struct nk_input *, enum nk_buttons)
NK_API nk_size nk_prog(struct nk_context *, nk_size cur, nk_size max, int modifyable)
NK_API int nk_filter_float(const struct nk_text_edit *, nk_rune unicode)
struct nk_vec2i begin
Definition: nuklear.h:2866
Definition: nuklear.h:3789
nk_handle callback_data
Definition: nuklear.h:2985
NK_API void nk_input_end(struct nk_context *)
NK_API int nk_button_pop_behavior(struct nk_context *)
float h
Definition: nuklear.h:457
struct nk_color selected_normal
Definition: nuklear.h:3473
NK_API void nk_layout_row(struct nk_context *, enum nk_layout_format, float height, int cols, const float *ratio)
NK_API void nk_layout_row_template_end(struct nk_context *)
Definition: nuklear.h:2042
Definition: nuklear.h:1721
struct nk_style_button dec_button
Definition: nuklear.h:3443
float rounding
Definition: nuklear.h:3635
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3391
NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a)
struct nk_style_edit edit
Definition: nuklear.h:3508
NK_API int nk_combo_string(struct nk_context *, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size)
struct nk_style_toggle option
Definition: nuklear.h:3660
struct nk_panel pan
Definition: nuklear.h:3977
Definition: nuklear.h:678
NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
struct nk_buffer_marker marker[NK_BUFFER_MAX]
Definition: nuklear.h:2563
NK_API int nk_combo_begin_image_text(struct nk_context *, const char *selected, int, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:2834
Definition: nuklear.h:2035
char string[1]
Definition: nuklear.h:2998
Definition: nuklear.h:2048
int heuristic(Location a, Location b)
Definition: findpath.cpp:58
nk_plugin_copy copy
Definition: nuklear.h:2694
Definition: nuklear.h:3258
struct nk_vec2 size offset
Definition: nuklear.h:462
struct nk_style_item normal
Definition: nuklear.h:3396
NK_API int nk_selectable_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int *value)
Definition: nuklear.h:666
struct nk_style_button node_minimize_button
Definition: nuklear.h:3572
Definition: nuklear.h:3730
nk_handle userdata
Definition: nuklear.h:3285
unsigned short line_thickness
Definition: nuklear.h:2935
NK_API int nk_check_text(struct nk_context *, const char *, int, int active)
short y
Definition: nuklear.h:2994
struct nk_text_edit text_edit
Definition: nuklear.h:4028
NK_API int nk_style_push_style_item(struct nk_context *, struct nk_style_item *, struct nk_style_item)
Definition: nuklear.h:2050
NK_API void nk_textedit_delete(struct nk_text_edit *, int where, int len)
int slot
Definition: nuklear.h:3715
NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed)
struct nk_style_item active
Definition: nuklear.h:3294
char name_string[NK_WINDOW_MAX_NAME]
Definition: nuklear.h:3846
Definition: nuklear.h:4004
typedef int(ENET_CALLBACK *ENetInterceptCallback)(struct _ENetHost *host
Definition: nuklear.h:2855
struct nk_page_element * prev
Definition: nuklear.h:3984
short x
Definition: nuklear.h:458
enum nk_anti_aliasing shape_AA
Definition: nuklear.h:984
Definition: nuklear.h:1710
struct nk_rect clip
Definition: nuklear.h:3008
struct nk_panel * layout
Definition: nuklear.h:3852
int length
Definition: nuklear.h:2997
NK_API void nk_style_set_font(struct nk_context *, const struct nk_user_font *)
struct nk_color left
Definition: nuklear.h:2893
Definition: nuklear.h:2872
struct nk_str string
Definition: nuklear.h:2726
nk_handle userdata
Definition: nuklear.h:3513
Definition: nuklear.h:466
Definition: nuklear.h:1884
#define const
Definition: zconf.h:196
short char_storage
Definition: nuklear.h:2701
short redo_char_point
Definition: nuklear.h:2710
int sel_start
Definition: nuklear.h:3823
struct nk_command header
Definition: nuklear.h:2864
short x
Definition: nuklear.h:2983
struct nk_clipboard clip
Definition: nuklear.h:4009
float border_cursor
Definition: nuklear.h:3436
NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color)
struct nk_vec2 content_padding
Definition: nuklear.h:3557
unsigned short line_thickness
Definition: nuklear.h:2875
enum nk_style_item_type type
Definition: nuklear.h:3254
NK_API void nk_label_colored(struct nk_context *, const char *, nk_flags align, struct nk_color)
struct nk_style_item active
Definition: nuklear.h:3592
Definition: nuklear.h:3830
Definition: nuklear.h:471
struct nk_color text_normal
Definition: nuklear.h:3302
Definition: nuklear.h:690
struct nk_color label_hover
Definition: nuklear.h:3540
Definition: nuklear.h:2044
NK_API int nk_check_label(struct nk_context *, const char *, int active)
struct nk_command header
Definition: nuklear.h:2941
NK_API void nk_window_set_bounds(struct nk_context *, struct nk_rect bounds)
nk_layout_format
Definition: nuklear.h:475
struct nk_color bar_filled
Definition: nuklear.h:3366
Definition: nuklear.h:2051
Definition: nuklear.h:3290
Definition: nuklear.h:452
Definition: nuklear.h:3002
short y
Definition: nuklear.h:456
NK_API void nk_end(struct nk_context *ctx)
NK_API int nk_menu_begin_symbol(struct nk_context *, const char *, enum nk_symbol_type, struct nk_vec2 size)
NK_API int nk_strfilter(const char *text, const char *regexp)
NK_API void nk_combobox_string(struct nk_context *, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size)
nk_text_width_f width
Definition: nuklear.h:2366
char buffer[NK_MAX_NUMBER_BUFFER]
Definition: nuklear.h:3832
Definition: nuklear.h:494
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3316
NK_API char * nk_str_get(struct nk_str *)
NK_UINT8 nk_byte
Definition: nuklear.h:396
#define NK_CHART_MAX_SLOT
Definition: nuklear.h:3686
struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]
Definition: nuklear.h:2705
unsigned short h
Definition: nuklear.h:2877
Definition: nuklear.h:2561
Definition: nuklear.h:460
Definition: nuklear.h:493
NK_API int nk_str_append_str_runes(struct nk_str *, const nk_rune *)
NK_API struct nk_color nk_rgba_fv(const float *rgba)
struct nk_config_stack_float floats
Definition: nuklear.h:3954
nk_uint x
Definition: nuklear.h:463
struct nk_style_button tab_maximize_button
Definition: nuklear.h:3569
#define NK_UNUSED(x)
Definition: nuklear.h:4052
int down
Definition: nuklear.h:3060
Definition: nuklear.h:3253
NK_INT16 nk_short
Definition: nuklear.h:397
short x
Definition: nuklear.h:2884
NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context *)
Definition: nuklear.h:1877
NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context *)
NK_API struct nk_rect nk_window_get_content_region(struct nk_context *)
NK_API int nk_select_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int value)
float grow_factor
Definition: nuklear.h:2571
struct nk_vec2 uv
Definition: nuklear.h:979
nk_uint * scroll_pointer
Definition: nuklear.h:1684
Definition: nuklear.h:452
Definition: nuklear.h:471
NK_API void nk_layout_space_begin(struct nk_context *, enum nk_layout_format, float height, int widget_count)
unsigned int seq
Definition: nuklear.h:4042
Definition: nuklear.h:454
int select_end
Definition: nuklear.h:3836
nk_text_edit_mode
Definition: nuklear.h:2718
struct nk_config_stack_color colors
Definition: nuklear.h:3957
struct nk_edit_state edit
Definition: nuklear.h:3858
struct nk_color label_active
Definition: nuklear.h:3541
NK_API void nk_style_from_table(struct nk_context *, const struct nk_color *)
int sel_end
Definition: nuklear.h:3824
#define NK_UINT8
Definition: nuklear.h:340
struct nk_input input
Definition: nuklear.h:4006
NK_API int nk_button_label(struct nk_context *, const char *title)
#define NK_MAX(a, b)
Definition: nuklear.h:316
const struct nk_user_font * font
Definition: nuklear.h:3650
float w
Definition: nuklear.h:3756
enum nk_button_behavior button_behavior
Definition: nuklear.h:4011
struct nk_context * ctx
unsigned short table_size
Definition: nuklear.h:3863
NK_API int nk_button_text(struct nk_context *, const char *title, int len)
#define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)
Definition: nuklear.h:4061
NK_API void nk_menubar_begin(struct nk_context *)
NK_API int nk_style_push_float(struct nk_context *, float *, float)
#define NK_PTR_TO_UINT(x)
Definition: nuklear.h:4082
#define NK_FONT_STACK_SIZE
Definition: nuklear.h:3901
NK_API int nk_combo_item_label(struct nk_context *, const char *, nk_flags alignment)
NK_API int nk_button_image_label(struct nk_context *, struct nk_image img, const char *, nk_flags text_alignment)
NK_API int nk_button_image_text(struct nk_context *, struct nk_image img, const char *, int, nk_flags alignment)
Definition: nuklear.h:673
Definition: nuklear.h:2697
NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color)
NK_API int nk_str_insert_str_char(struct nk_str *, int pos, const char *)
struct nk_vec2i points[1]
Definition: nuklear.h:2968
Definition: nuklear.h:2018
struct nk_vec2 padding
Definition: nuklear.h:3377
NK_API int nk_menu_begin_label(struct nk_context *, const char *, nk_flags align, struct nk_vec2 size)
unsigned char grabbed
Definition: nuklear.h:3055
NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color)
unsigned char mode
Definition: nuklear.h:3826
NK_API int nk_style_pop_flags(struct nk_context *)
NK_API int nk_button_symbol_text_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API struct nk_color nk_rgb_hex(const char *rgb)
struct nk_style_item hover
Definition: nuklear.h:3534
nk_symbol_type
Definition: nuklear.h:489
NK_API struct nk_color nk_rgb_bv(const nk_byte *rgb)
NK_API int nk_str_insert_str_utf8(struct nk_str *, int pos, const char *)
struct nk_allocator pool
Definition: nuklear.h:2565
NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region)
struct nk_color text_background
Definition: nuklear.h:3305
short cy
Definition: nuklear.h:2942
Definition: nuklear.h:687
NK_API void nk_plot_function(struct nk_context *, enum nk_chart_type, void *userdata, float(*value_getter)(void *user, int index), int count, int offset)
struct nk_vec2 image_padding
Definition: nuklear.h:3281
NK_API nk_rune nk_str_rune_at(const struct nk_str *, int pos)
struct nk_scroll offset
Definition: nuklear.h:3757
NK_API int nk_style_pop_font(struct nk_context *)
struct nk_style_item hover
Definition: nuklear.h:3293
nk_command_clipping
Definition: nuklear.h:3001
tuple output
Definition: gtest_output_test.py:321
Definition: nuklear.h:3063
int columns
Definition: nuklear.h:3736
unsigned short r
Definition: nuklear.h:2934
int text_len
Definition: nuklear.h:3066
NK_INT32 nk_int
Definition: nuklear.h:399
NK_API int nk_tree_state_push(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states *state)
float border
Definition: nuklear.h:3479
NK_API void nk_input_unicode(struct nk_context *, nk_rune)
Definition: nuklear.h:698
NK_API void nk_textedit_redo(struct nk_text_edit *)
NK_API void nk_menu_close(struct nk_context *)
Definition: nuklear.h:472
NK_API struct nk_vec2 nk_rect_size(struct nk_rect)
Definition: nuklear.h:671
struct nk_style_item background
Definition: nuklear.h:3520
NK_API void nk_str_init(struct nk_str *, const struct nk_allocator *, nk_size size)
NK_API struct nk_image nk_image_id(int)
short y
Definition: nuklear.h:2884
struct nk_color color
Definition: nuklear.h:2937
Definition: nuklear.h:3726
NK_API int nk_combo_begin_image(struct nk_context *, struct nk_image img, struct nk_vec2 size)
Definition: nuklear.h:2820
#define nk_vec2_len_sqr(a)
Definition: nuklear.h:4066
struct nk_style_button inc_button
Definition: nuklear.h:3509
void(* draw_begin)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:3286
struct nk_style_item active
Definition: nuklear.h:3424
struct nk_command header
Definition: nuklear.h:2917
Definition: nuklear.h:2055
Definition: nuklear.h:3245
NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color)
NK_API void nk_combo_end(struct nk_context *)
Definition: nuklear.h:2833
NK_API int nk_propertyi(struct nk_context *, const char *name, int min, int val, int max, int step, float inc_per_pixel)
Definition: nuklear.h:3693
nk_size calls
Definition: nuklear.h:2577
NK_API void nk_input_char(struct nk_context *, char)
Definition: nuklear.h:2881
NK_API void nk_color_dv(double *rgba_out, struct nk_color)
struct nk_page_element win[1]
Definition: nuklear.h:3990
#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1)
Definition: nuklear.h:4059
NK_API struct nk_vec2 nk_vec2v(const float *xy)
NK_API int nk_tooltip_begin(struct nk_context *, float width)
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3317
NK_API struct nk_rect nk_recti(int x, int y, int w, int h)
NK_API struct nk_panel * nk_window_get_panel(struct nk_context *)
struct nk_vec2 menu_padding
Definition: nuklear.h:3645
struct nk_color label_normal
Definition: nuklear.h:3495
nk_size offset
Definition: nuklear.h:2558
nk_show_states
Definition: nuklear.h:470
struct nk_color color
Definition: nuklear.h:3259
struct nk_style_item pressed
Definition: nuklear.h:3324
NK_API int nk_style_pop_color(struct nk_context *)
NK_API struct nk_color nk_rgba_iv(const int *rgba)
unsigned char single_line
Definition: nuklear.h:3827
struct nk_color selected_hover
Definition: nuklear.h:3474
NK_API void nk_chart_end(struct nk_context *)
short x
Definition: nuklear.h:2926
struct nk_command_buffer * buffer
Definition: nuklear.h:3775
float a
Definition: nuklear.h:454
struct nk_color menu_border_color
Definition: nuklear.h:3622
NK_API int nk_menu_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
Definition: nuklear.h:465
Definition: nuklear.h:1744
Definition: nuklear.h:3722
NK_API int nk_combo_begin_symbol_label(struct nk_context *, const char *selected, enum nk_symbol_type, struct nk_vec2 size)
Definition: nuklear.h:472
#define NK_ALIGN_PTR_BACK(x, mask)
Definition: nuklear.h:4093
NK_API int nk_style_push_vec2(struct nk_context *, struct nk_vec2 *, struct nk_vec2)
nk_heading
Definition: nuklear.h:465
#define nk_vec2_muls(a, t)
Definition: nuklear.h:4067
nk_style_colors
Definition: nuklear.h:2016
NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context *)
NK_API int nk_menu_begin_text(struct nk_context *, const char *title, int title_len, nk_flags align, struct nk_vec2 size)
struct nk_color background
Definition: nuklear.h:2992
struct nk_vec2i end
Definition: nuklear.h:2867
nk_handle userdata
Definition: nuklear.h:3010
Definition: nuklear.h:491
NK_API struct nk_rect nk_rectiv(const int *xywh)
unsigned short h
Definition: nuklear.h:461
struct nk_color border_color
Definition: nuklear.h:3565
NK_API struct nk_vec2 nk_widget_size(struct nk_context *)
NK_API void nk_layout_row_push(struct nk_context *, float value)
nk_flags text_alignment
Definition: nuklear.h:3306